Vous avez reçu un message "Your GitLab account has been locked ..." ? Pas d'inquiétude : lisez cet article https://docs.gricad-pages.univ-grenoble-alpes.fr/help/unlock/

Commit a0f23cc2 authored by EXT Arnaud Clère's avatar EXT Arnaud Clère
Browse files

If constexpr provide little performance improvement

Use IBind to share BindSupport<IBind,T> for common T
parent 3126a6e5
......@@ -19,6 +19,10 @@ TEMPLATE = app
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# C++17 allows replacing 'if /*constexpr*/' with 'if constepxr' with little performance improvement
#gcc:QMAKE_CXXFLAGS += -std=c++1z
#msvc:QMAKE_CXXFLAGS += /std=c++17
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
......
......@@ -266,7 +266,7 @@ public:
using TResult = Cur;
using TImpl = TImpl_;
static constexpr BindMode Mode = TImpl::Mode;
static Q_DECL_CONSTEXPR BindMode Mode = TImpl::Mode;
Cur(TImpl* i) : impl(i) { Q_ASSERT(impl); }
......@@ -308,10 +308,20 @@ private:
// //////////////////////////////////////////////////////////////////////////
// Base Cur<TImpl> implementations for BindMode Read and Write
struct IBind {};
template<> struct BindSupport<IBind,const char*> : BindNative {};
template<> struct BindSupport<IBind, QString> : BindNative {};
template<> struct BindSupport<IBind, QByteArray> : BindNative {};
template<> struct BindSupport<IBind, bool> : BindNative {};
template<> struct BindSupport<IBind, float> : BindNative {};
template<> struct BindSupport<IBind, double> : BindNative {};
template<> struct BindSupport<IBind, qulonglong> : BindNative {};
template<> struct BindSupport<IBind, qlonglong> : BindNative {};
//! Interface for runtime Cur<TImpl> implementations with BindMode::Write and a fixed subset of scalar types
struct IWriter
struct IWriter : public IBind
{
static constexpr BindMode Mode = BindMode::Write;
static Q_DECL_CONSTEXPR BindMode Mode = BindMode::Write;
virtual ~IWriter() = default;
......@@ -350,23 +360,16 @@ struct IWriter
virtual void _setChoice(bool) {}
virtual void _reportError(const char*) {}
};
template<> struct BindSupport<IWriter,const char*> : BindNative {};
template<> struct BindSupport<IWriter, QString> : BindNative {};
template<> struct BindSupport<IWriter, QByteArray> : BindNative {};
template<> struct BindSupport<IWriter, bool> : BindNative {};
template<> struct BindSupport<IWriter, float> : BindNative {};
template<> struct BindSupport<IWriter, double> : BindNative {};
template<> struct BindSupport<IWriter, qulonglong> : BindNative {};
template<> struct BindSupport<IWriter, qlonglong> : BindNative {};
template<typename T> struct BindSupport<IWriter,T> : BindSupport<IBind,T> {};
//! Writer with standard native types that replaces compile-time TResult with runtime IWriter
//! \remark Useful for code that do not know the Writer in advance like QLogger defined below
using QWriter = Cur<IWriter>;
//! Interface for runtime Cur<TImpl> implementations with BindMode::Read and a fixed subset of scalar types
struct IReader
struct IReader : public IBind
{
static constexpr BindMode Mode = BindMode::Read;
static Q_DECL_CONSTEXPR BindMode Mode = BindMode::Read;
virtual ~IReader() = default;
......@@ -423,14 +426,7 @@ struct IReader
virtual void _setChoice(bool) {}
virtual void _reportError(const char*) {}
};
template<> struct BindSupport<IReader,const char*> : BindNative {};
template<> struct BindSupport<IReader, QString> : BindNative {};
template<> struct BindSupport<IReader, QByteArray> : BindNative {};
template<> struct BindSupport<IReader, bool> : BindNative {};
template<> struct BindSupport<IReader, float> : BindNative {};
template<> struct BindSupport<IReader, double> : BindNative {};
template<> struct BindSupport<IReader, qulonglong> : BindNative {};
template<> struct BindSupport<IReader, qlonglong> : BindNative {};
template<typename T> struct BindSupport<IReader,T> : BindSupport<IBind,T> {};
//! Reader with standard native types that replaces compile-time TResult with runtime IReader
using QReader = Cur<IReader>;
......@@ -481,16 +477,13 @@ struct QBind<TResult, std::nullptr_t> {
template<class TResult, typename T>
struct QBind<TResult, T, typename std::enable_if<std::is_unsigned<T>::value && std::is_integral<T>::value && !std::is_same<T,bool>::value>::type> {
static TResult bind(Val<TResult>&& dst, T&& t) {
/*constexpr*/ if (TResult::Mode==Write) {
return dst.bind(qulonglong(t));
}
static_assert(TResult::Mode==Write,"Unsupported TResult::Mode");
return dst.bind(qulonglong(t));
}
static TResult bind(Val<TResult>&& src, T& t) {
/*constexpr*/ if (TResult::Mode==Write) {
if /*constexpr*/ (TResult::Mode==Write) {
return bind(std::move(src),T(t));
}
else /*constexpr*/ if (TResult::Mode==Read) {
else if /*constexpr*/ (TResult::Mode==Read) {
qulonglong u; auto r=src.bind(u); if (r) { t=u; } return r;
}
}
......@@ -498,16 +491,13 @@ struct QBind<TResult, T, typename std::enable_if<std::is_unsigned<T>::value && s
template<class TResult, typename T>
struct QBind<TResult, T, typename std::enable_if<std::is_signed<T>::value && std::is_integral<T>::value && !std::is_same<T,bool>::value>::type> {
static TResult bind(Val<TResult>&& dst, T&& t) {
// /*constexpr*/ if (TResult::Mode==Write) {
return dst.bind(qlonglong(t));
// }
// FIXME static_assert(TResult::Mode==Write,"Unsupported TResult::Mode");
return dst.bind(qlonglong(t));
}
static TResult bind(Val<TResult>&& src, T& t) {
/*constexpr*/ if (TResult::Mode==Write) {
if /*constexpr*/ (TResult::Mode==Write) {
return bind(std::move(src),T(t));
}
else /*constexpr*/ if (TResult::Mode==Read) {
else if /*constexpr*/ (TResult::Mode==Read) {
qlonglong u; auto r=src.bind(u); if (r) { t=u; } return r;
}
}
......@@ -516,7 +506,7 @@ struct QBind<TResult, T, typename std::enable_if<std::is_signed<T>::value && std
template<class TResult, typename T, unsigned Size>
struct QBind<TResult, T[Size]> {
static TResult bind(Val<TResult>&& src, T(& dst)[Size]) {
/*constexpr*/ if (TResult::Mode==Write) {
if /*constexpr*/ (TResult::Mode==Write) {
quint32 size=Size;
auto s(src.sequence(&size));
for (auto&& t : dst) {
......@@ -524,7 +514,7 @@ struct QBind<TResult, T[Size]> {
}
return s;
}
else /*constexpr*/ if (TResult::Mode==Read) {
else if /*constexpr*/ (TResult::Mode==Read) {
auto s(src.sequence());
Val<Seq<TResult>> i; unsigned j=0;
while ((i = s.item())) {
......@@ -545,16 +535,16 @@ struct QBind<TResult, T[Size]> {
template<class TResult>
struct QBind<TResult, QString> {
static TResult bind(Val<TResult>&& dst, QString&& src) {
/*constexpr*/ if (TResult::Mode==Write) {
if /*constexpr*/ (TResult::Mode==Write) {
return dst.bind(src.toUtf8().constData());
}
//static_assert(TResult::Mode==Write,"Unsupported TResult::Mode");
}
static TResult bind(Val<TResult>&& src, QString& dst) {
/*constexpr*/ if (TResult::Mode==Write) {
if /*constexpr*/ (TResult::Mode==Write) {
return bind(std::move(src),QString(dst));
}
else /*constexpr*/ if (TResult::Mode==Read) {
else if /*constexpr*/ (TResult::Mode==Read) {
QByteArray ba;
auto r = src.bind(ba); // FIXME QByteArray is raw data that does not necessarily represent a utf8 string
if (r) {
......@@ -570,7 +560,7 @@ struct QBind<TResult, QString> {
template<class TResult, typename T>
struct QBind<TResult, QVector<T>> {
static TResult bind(Val<TResult>&& dst, QVector<T>&& src) {
// /*constexpr*/ if (TResult::Mode==Write) {
// if /*constexpr*/ (TResult::Mode==Write) {
quint32 size=src.size();
auto s(dst.sequence(&size));
for (auto&& t : src) {
......@@ -581,7 +571,7 @@ struct QBind<TResult, QVector<T>> {
// static_assert(TResult::Mode==Write,"Unsupported TResult::Mode");
}
static TResult bind(Val<TResult>&& src, QVector<T>& dst) {
/*constexpr*/ if (TResult::Mode==Write) {
if /*constexpr*/ (TResult::Mode==Write) {
quint32 size=dst.size();
auto s(src.sequence(&size));
for (auto&& t : dst) {
......@@ -589,7 +579,7 @@ struct QBind<TResult, QVector<T>> {
}
return s;
}
else /*constexpr*/ if (TResult::Mode==Read) {
else if /*constexpr*/ (TResult::Mode==Read) {
auto s(src.sequence());
Val<Seq<TResult>> i;
while ((i = s.item())) {
......@@ -607,7 +597,7 @@ struct QBind<TResult, QVector<T>> {
template<class TResult, typename T>
struct QBind<TResult, QList<T>> {
static TResult bind(Val<TResult>&& dst, QList<T>&& src) {
/*constexpr*/ if (TResult::Mode==Write) {
if /*constexpr*/ (TResult::Mode==Write) {
quint32 size=quint32(src.size());
auto s(dst.sequence(&size));
for (auto&& item : src) {
......@@ -618,10 +608,10 @@ struct QBind<TResult, QList<T>> {
static_assert(TResult::Mode==Write,"Unsupported TResult::Mode");
}
static TResult bind(Val<TResult>&& src, QList<T>& dst) {
/*constexpr*/ if (TResult::Mode==Write) {
if /*constexpr*/ (TResult::Mode==Write) {
return bind(std::move(src),QList<T>(dst));
}
else /*constexpr*/ if (TResult::Mode==Read) {
else if /*constexpr*/ (TResult::Mode==Read) {
auto s(src.sequence());
Val<Seq<TResult>> i;
while ((i = s.item())) {
......@@ -639,7 +629,7 @@ struct QBind<TResult, QList<T>> {
template<class TResult, typename T>
struct QBind<TResult, QMap<QString,T>> {
static TResult bind(Val<TResult>&& dst, QMap<QString,T>&& src) {
/*constexpr*/ if (TResult::Mode==Write) {
if /*constexpr*/ (TResult::Mode==Write) {
quint32 size=quint32(src.size());
auto s(dst.record(&size));
for (QString key : src.keys()) {
......@@ -650,10 +640,10 @@ struct QBind<TResult, QMap<QString,T>> {
static_assert(TResult::Mode==Write,"Unsupported TResult::Mode");
}
static TResult bind(Val<TResult>&& src, QMap<QString,T>& dst) {
/*constexpr*/ if (TResult::Mode==Write) {
if /*constexpr*/ (TResult::Mode==Write) {
return bind(std::move(src),QMap<QString,T>(dst));
}
else /*constexpr*/ if (TResult::Mode==Read) {
else if /*constexpr*/ (TResult::Mode==Read) {
auto s(src.record());
QUtf8String name; Val<Rec<TResult>> i;
while ((i = s.item(name))) {
......@@ -689,7 +679,7 @@ template<class TSrcResult, class TDst>
struct QBind<TSrcResult, Val<TDst>> {
static TSrcResult bind(Val<TSrcResult>&& src, Val<TDst>&& dst) {
static_assert(!(TSrcResult::Mode==Write && TDst::Mode==Read),"Try inverting src and dst");
/*constexpr*/ if (TSrcResult::Mode==Read && TDst::Mode==Write) {
if /*constexpr*/ (TSrcResult::Mode==Read && TDst::Mode==Write) {
TSrcResult srcRes;
{
QScopedChoice<Val<TSrcResult>> choice(src);
......
......@@ -139,7 +139,6 @@ protected:
bool _bind ( float&& n) { return Q_LIKELY(putSimpleValue(cbor::Next32BitFloat)) && putBigEndian(n); }
bool _bind ( double&& n) { return Q_LIKELY(putSimpleValue(cbor::Next64BitFloat)) && putBigEndian(n); }
// This dispatch would be more simple with C++17 constexpr if
bool _bind ( qulonglong&& t) { return putInteger(quint64( t), cbor::UnsignedIntType); }
bool _bind ( qlonglong&& t) { return t<0 ? putInteger(quint64(-1-t), cbor::NegativeIntType) // see https://tools.ietf.org/html/rfc7049#section-2.1
: putInteger(quint64( t), cbor::UnsignedIntType); }
......
......@@ -420,7 +420,7 @@ private:
template<class TResult>
struct QBind<TResult, QJsonValue> {
static TResult bind(Val<TResult>&& v, QJsonValue&& j) {
/*constexpr*/ if (TResult::Mode==Write) {
if /*constexpr*/ (TResult::Mode==Write) {
if (j.isObject()) return v.bind(j.toObject());
if (j.isArray ()) return v.bind(j.toArray ());
if (j.isBool ()) return v.bind(j.toBool ());
......@@ -428,7 +428,7 @@ struct QBind<TResult, QJsonValue> {
if (j.isString()) return v.bind(j.toString());
return v.null();
}
else /*constexpr*/ if (TResult::Mode==Read) {
else if /*constexpr*/ (TResult::Mode==Read) {
TResult r;
{
QScopedChoice<Val<TResult>> choice(v);
......@@ -450,7 +450,7 @@ struct QBind<TResult, QJsonValue> {
template<class TResult>
struct QBind<TResult, QJsonArray> {
static TResult bind(Val<TResult>&& v, QJsonArray&& j) {
/*constexpr*/ if (TResult::Mode==Write) {
if /*constexpr*/ (TResult::Mode==Write) {
quint32 size=quint32(j.size());
auto s(v.sequence(&size));
for (QJsonValue&& item : j) {
......@@ -458,7 +458,7 @@ struct QBind<TResult, QJsonArray> {
}
return s;
}
else /*constexpr*/ if (TResult::Mode==Read) {
else if /*constexpr*/ (TResult::Mode==Read) {
auto s(v.sequence());
Val<Seq<TResult>> i;
while ((i = s.item())) {
......@@ -477,7 +477,7 @@ struct QBind<TResult, QJsonArray> {
template<class TResult>
struct QBind<TResult, QJsonObject> {
static TResult bind(Val<TResult>&& v, QJsonObject&& j) {
/*constexpr*/ if (TResult::Mode==Write) {
if /*constexpr*/ (TResult::Mode==Write) {
quint32 size=quint32(j.size());
auto s(v.record(&size));
for (QString key : j.keys()) {
......@@ -485,7 +485,7 @@ struct QBind<TResult, QJsonObject> {
}
return s;
}
else /*constexpr*/ if (TResult::Mode==Read) {
else if /*constexpr*/ (TResult::Mode==Read) {
auto s(v.record());
QByteArray k; Val<Rec<TResult>> i;
while ((i = s.item(k))) {
......
......@@ -138,7 +138,7 @@ private:
template<class TResult>
struct QBind<TResult, QVariant> {
static TResult bind(Val<TResult>&& dst, QVariant&& src) {
/*constexpr*/ if (TResult::Mode==Write) {
if /*constexpr*/ (TResult::Mode==Write) {
if (src.type()==QVariant::List ) return dst.bind(src.value<QVariantList>()); // TODO QSequentialIterable ?
if (src.type()==QVariant::Map ) return dst.bind(src.value<QVariantMap >()); // TODO QAssociativeIterable ?
// TODO QVariant::Hash
......@@ -162,7 +162,7 @@ struct QBind<TResult, QVariant> {
static_assert(TResult::Mode!=Write,"Unsupported TResult::Mode");
}
static TResult bind(Val<TResult>&& src, QVariant& dst) {
/*constexpr*/ if (TResult::Mode==Write) {
if /*constexpr*/ (TResult::Mode==Write) {
return bind(std::move(src),std::move(dst));
}
static_assert(TResult::Mode!=Write,"Unsupported TResult::Mode");
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment