diff --git a/src/blackmisc/compare.h b/src/blackmisc/compare.h index af0b820df..99cb88f49 100644 --- a/src/blackmisc/compare.h +++ b/src/blackmisc/compare.h @@ -57,7 +57,7 @@ namespace BlackMisc { auto meta = introspect().without(MetaFlags()); bool result = baseEquals(static_cast *>(&a), static_cast *>(&b)); - meta.forEachMemberPair(a, b, [ & ](auto &&... args) { result = result && EqualsByMetaClass::membersEqual(std::forward(args)...); }); + meta.forEachMember([ & ](auto member) { result = result && EqualsByMetaClass::membersEqual(member.in(a), member.in(b), member.m_flags); }); return result; } template static bool baseEquals(const T *a, const T *b) { return *a == *b; } @@ -122,7 +122,7 @@ namespace BlackMisc auto meta = introspect().without(MetaFlags()); bool result = baseLess(static_cast *>(&a), static_cast *>(&b)); bool gt = baseLess(static_cast *>(&b), static_cast *>(&a)); - meta.forEachMemberPair(a, b, [ & ](auto &&... args) { result = result || LessThanByMetaClass::membersLess(gt, std::forward(args)...); }); + meta.forEachMember([ & ](auto member) { result = result || LessThanByMetaClass::membersLess(gt, member.in(a), member.in(b), member.m_flags); }); return result; } template static bool baseLess(const T *a, const T *b) { return *a < *b; } @@ -158,7 +158,7 @@ namespace BlackMisc { auto meta = introspect().without(MetaFlags()); int result = baseCompare(static_cast *>(&a), static_cast *>(&b)); - meta.forEachMemberPair(a, b, [ & ](auto &&... args) { result = result ? result : CompareByMetaClass::membersCompare(std::forward(args)...); }); + meta.forEachMember([ & ](auto member) { result = result ? result : CompareByMetaClass::membersCompare(member.in(a), member.in(b), member.m_flags); }); return result; } template static int baseCompare(const T *a, const T *b) { return compare(*a, *b); } diff --git a/src/blackmisc/dbus.h b/src/blackmisc/dbus.h index 79be3d19e..1e656de57 100644 --- a/src/blackmisc/dbus.h +++ b/src/blackmisc/dbus.h @@ -84,7 +84,7 @@ namespace BlackMisc { baseMarshall(static_cast *>(derived()), arg); auto meta = introspect().without(MetaFlags()); - meta.forEachMember(*derived(), [ & ](const auto &member) { Private::marshallMember(arg, member); }); + meta.forEachMember([ &, this ](auto member) { Private::marshallMember(arg, member.in(*derived())); }); } //! Unmarshall without begin/endStructure, for when composed within another object @@ -92,7 +92,7 @@ namespace BlackMisc { baseUnmarshall(static_cast *>(derived()), arg); auto meta = introspect().without(MetaFlags()); - meta.forEachMember(*derived(), [ & ](auto &member) { Private::unmarshallMember(arg, member); }); + meta.forEachMember([ &, this ](auto member) { Private::unmarshallMember(arg, member.in(*derived())); }); } private: diff --git a/src/blackmisc/dictionary.h b/src/blackmisc/dictionary.h index 00379e8b1..7a059b50e 100644 --- a/src/blackmisc/dictionary.h +++ b/src/blackmisc/dictionary.h @@ -72,10 +72,12 @@ namespace BlackMisc }; // Work around MSVC2015 bug affecting generic lambda + template struct Hasher { - template - void operator()(const T &object) { m_hash ^= qHash(object); } + template + void operator()(const U &member) { m_hash ^= qHash(member.in(m_object)); } + const T &m_object; uint &m_hash; }; @@ -496,7 +498,7 @@ namespace BlackMisc { uint hash = baseHash(static_cast *>(&value)); auto meta = introspect().without(MetaFlags()); - meta.forEachMember(value, Private::Hasher { hash }); + meta.forEachMember(Private::Hasher { value, hash }); return hash; } diff --git a/src/blackmisc/json.h b/src/blackmisc/json.h index 197a42043..aeb775dc3 100644 --- a/src/blackmisc/json.h +++ b/src/blackmisc/json.h @@ -355,9 +355,9 @@ namespace BlackMisc { QJsonObject json; auto meta = introspect().without(MetaFlags()); - meta.forEachMemberName(*derived(), [ & ](const auto & member, CExplicitLatin1String name) + meta.forEachMember([ &, this ](auto member) { - json << std::make_pair(name.toJsonKey(), std::cref(member)); + json << std::make_pair(CExplicitLatin1String(member.latin1Name()).toJsonKey(), std::cref(member.in(*derived()))); }); return Json::appendJsonObject(json, baseToJson(static_cast *>(derived()))); } @@ -374,18 +374,18 @@ namespace BlackMisc { baseConvertFromJson(static_cast *>(derived()), json); auto meta = introspect().without(MetaFlags()); - meta.forEachMemberName(*derived(), [ & ](auto & member, CExplicitLatin1String name) + meta.forEachMember([ &, this ](auto member) { - const auto value = json.value(name); + const auto value = json.value(CExplicitLatin1String(member.latin1Name())); if (value.isUndefined()) { constexpr bool required = false; //! \fixme add RequiredForJson flag in metaclass system - if (required) { throw CJsonException(QStringLiteral("Missing required member '%1'").arg(name.m_latin1)); } + if (required) { throw CJsonException(QStringLiteral("Missing required member '%1'").arg(member.latin1Name())); } } else { - CJsonScope scope(name.m_latin1); - value >> member; + CJsonScope scope(member.latin1Name()); + value >> member.in(*derived()); } }); } diff --git a/src/blackmisc/metaclass.h b/src/blackmisc/metaclass.h index e4d9059f5..49a239eea 100644 --- a/src/blackmisc/metaclass.h +++ b/src/blackmisc/metaclass.h @@ -223,57 +223,16 @@ namespace BlackMisc template static auto without(Flags) { return filter(MaskSequence<(! members().at(index()).has(Flags()))...>()); } - //! For each member in object, pass member as argument to visitor function. - //! @{ + //! For each metamember in metaclass, pass metamember as argument to visitor function. template - static void forEachMember(T &object, F &&visitor) + static void forEachMember(F &&visitor) { - forEachImpl([ & ](auto &&member, auto) { std::forward(visitor)(member.in(object)); }); + // parameter pack swallow idiom + static_cast(std::initializer_list + { + (static_cast(std::forward(visitor)(members().at(index()))), 0)... + }); } - template - static void forEachMember(const T &object, F &&visitor) - { - forEachImpl([ & ](auto &&member, auto) { std::forward(visitor)(member.in(object)); }); - } - //! @} - - //! For each member in object pair, pass member pair as arguments to visitor function. - //! @{ - template - static void forEachMemberPair(T &left, T &right, F &&visitor) - { - forEachImpl([ & ](auto &&member, auto flags) { std::forward(visitor)(member.in(left), member.in(right), flags); }); - } - template - static void forEachMemberPair(const T &left, T &right, F &&visitor) - { - forEachImpl([ & ](auto &&member, auto flags) { std::forward(visitor)(member.in(left), member.in(right), flags); }); - } - template - static void forEachMemberPair(T &left, const T &right, F &&visitor) - { - forEachImpl([ & ](auto &&member, auto flags) { std::forward(visitor)(member.in(left), member.in(right), flags); }); - } - template - static void forEachMemberPair(const T &left, const T &right, F &&visitor) - { - forEachImpl([ & ](auto &&member, auto flags) { std::forward(visitor)(member.in(left), member.in(right), flags); }); - } - //! @} - - //! For each member in object, pass member and its name as arguments to visitor function. - //! @{ - template - static void forEachMemberName(T &object, F &&visitor) - { - forEachImpl([ & ](auto &&member, auto) { std::forward(visitor)(member.in(object), member.latin1Name()); }); - } - template - static void forEachMemberName(const T &object, F &&visitor) - { - forEachImpl([ & ](auto &&member, auto) { std::forward(visitor)(member.in(object), member.latin1Name()); }); - } - //! @} private: template @@ -286,16 +245,6 @@ namespace BlackMisc using index = std::integral_constant; constexpr static auto members() BLACK_TRAILING_RETURN(MetaClass::getMemberList()) { return MetaClass::getMemberList(); } - - template - static void forEachImpl(F &&visitor) - { - // parameter pack swallow idiom - static_cast(std::initializer_list - { - (static_cast(std::forward(visitor)(members().at(index()), MetaFlags()).m_flags>())), 0)... - }); - } }; namespace Private diff --git a/src/blackmisc/simulation/aircraftmodel.cpp b/src/blackmisc/simulation/aircraftmodel.cpp index c2cc71e0a..b3580c8ce 100644 --- a/src/blackmisc/simulation/aircraftmodel.cpp +++ b/src/blackmisc/simulation/aircraftmodel.cpp @@ -106,10 +106,10 @@ namespace BlackMisc { QJsonObject json; auto meta = introspect().without(MetaFlags()); - meta.forEachMemberName(*this, [ & ](const auto & member, CExplicitLatin1String name) + meta.forEachMember([ &, this ](auto member) { - auto &&maybeMemo = helper.maybeMemoize(member); - json << std::make_pair(name.toJsonKey(), std::cref(maybeMemo)); + auto &&maybeMemo = helper.maybeMemoize(member.in(*this)); + json << std::make_pair(CExplicitLatin1String(member.latin1Name()).toJsonKey(), std::cref(maybeMemo)); }); return json; } @@ -117,10 +117,10 @@ namespace BlackMisc void CAircraftModel::convertFromMemoizedJson(const QJsonObject &json, const MemoHelper::CUnmemoizer &helper) { auto meta = introspect().without(MetaFlags()); - meta.forEachMemberName(*this, [ & ](auto & member, CExplicitLatin1String name) + meta.forEachMember([ &, this ](auto member) { - auto it = json.find(name); - if (it != json.end()) { it.value() >> helper.maybeUnmemoize(member).get(); } + auto it = json.find(CExplicitLatin1String(member.latin1Name())); + if (it != json.end()) { it.value() >> helper.maybeUnmemoize(member.in(*this)).get(); } }); }