mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-03-22 23:05:36 +08:00
Use if constexpr in metaclass visitor functions
This commit is contained in:
@@ -12,7 +12,6 @@
|
||||
#define BLACKMISC_METACLASS_H
|
||||
|
||||
#include "blackmisc/invoke.h"
|
||||
#include "blackmisc/integersequence.h"
|
||||
#include <QHash>
|
||||
#include <QString>
|
||||
#include <QLatin1String>
|
||||
@@ -169,7 +168,7 @@ namespace BlackMisc
|
||||
|
||||
//! True if m_flags contains all flags.
|
||||
template <typename Flags2>
|
||||
constexpr bool has(Flags2 flags) const { return (MetaFlags<Flags>() & flags) == flags; }
|
||||
static constexpr bool has(Flags2 flags) { return (MetaFlags<Flags>() & flags) == flags; }
|
||||
|
||||
//! Invoke the member on an instance of the value class.
|
||||
template <typename T, typename... Ts>
|
||||
@@ -266,34 +265,12 @@ namespace BlackMisc
|
||||
class CMetaClassIntrospector
|
||||
{
|
||||
public:
|
||||
//! Return a CMetaClassIntrospector<T> covering only those members which have the given flags.
|
||||
//! \see BlackMisc::MetaFlags
|
||||
template <typename Flags>
|
||||
constexpr static auto with(Flags) { return filter(MaskSequence<(members().at(index<Is>()).has(Flags()))...>()); }
|
||||
|
||||
//! Return a CMetaClassIntrospector<T> covering only those members which do not have the given flags.
|
||||
//! \see BlackMisc::MetaFlags
|
||||
template <typename Flags>
|
||||
constexpr static auto without(Flags) { return filter(MaskSequence<(! members().at(index<Is>()).has(Flags()))...>()); }
|
||||
|
||||
//! For each metamember in metaclass, pass metamember as argument to visitor function.
|
||||
template <typename F>
|
||||
static void forEachMember(F &&visitor)
|
||||
{
|
||||
(static_cast<void>(std::forward<F>(visitor)(members().at(index<Is>()))), ...);
|
||||
(static_cast<void>(std::forward<F>(visitor)(MetaClass::getMemberList().at(std::integral_constant<size_t, Is>()))), ...);
|
||||
}
|
||||
|
||||
private:
|
||||
template <bool... Mask>
|
||||
using MaskSequence = Private::MaskSequence<std::index_sequence<Is...>, Mask...>;
|
||||
|
||||
template <size_t... Js>
|
||||
constexpr static auto filter(std::index_sequence<Js...>) { return CMetaClassIntrospector<T, MetaClass, Js...>(); }
|
||||
|
||||
template <size_t I>
|
||||
using index = std::integral_constant<size_t, I>;
|
||||
|
||||
constexpr static auto members() { return MetaClass::getMemberList(); }
|
||||
};
|
||||
// *INDENT-ON*
|
||||
|
||||
|
||||
@@ -58,9 +58,14 @@ namespace BlackMisc
|
||||
private:
|
||||
static bool equals(const Derived &a, const Derived &b)
|
||||
{
|
||||
constexpr auto meta = introspect<Derived>().without(MetaFlags<DisabledForComparison>());
|
||||
bool result = baseEquals(static_cast<const TBaseOfT<Derived> *>(&a), static_cast<const TBaseOfT<Derived> *>(&b));
|
||||
meta.forEachMember([ & ](auto member) { result = result && EqualsByMetaClass::membersEqual(member.in(a), member.in(b), member.m_flags); });
|
||||
introspect<Derived>().forEachMember([ & ](auto member)
|
||||
{
|
||||
if constexpr (!decltype(member)::has(MetaFlags<DisabledForComparison>()))
|
||||
{
|
||||
result = result && EqualsByMetaClass::membersEqual(member.in(a), member.in(b), member.m_flags);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
template <typename T> static bool baseEquals(const T *a, const T *b) { return *a == *b; }
|
||||
@@ -119,10 +124,15 @@ namespace BlackMisc
|
||||
private:
|
||||
static bool less(const Derived &a, const Derived &b)
|
||||
{
|
||||
constexpr auto meta = introspect<Derived>().without(MetaFlags<DisabledForComparison>());
|
||||
bool result = baseLess(static_cast<const TBaseOfT<Derived> *>(&a), static_cast<const TBaseOfT<Derived> *>(&b));
|
||||
bool gt = baseLess(static_cast<const TBaseOfT<Derived> *>(&b), static_cast<const TBaseOfT<Derived> *>(&a));
|
||||
meta.forEachMember([ & ](auto member) { result = result || LessThanByMetaClass::membersLess(gt, member.in(a), member.in(b), member.m_flags); });
|
||||
introspect<Derived>().forEachMember([ & ](auto member)
|
||||
{
|
||||
if constexpr (!decltype(member)::has(MetaFlags<DisabledForComparison>()))
|
||||
{
|
||||
result = result || LessThanByMetaClass::membersLess(gt, member.in(a), member.in(b), member.m_flags);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
template <typename T> static bool baseLess(const T *a, const T *b) { return *a < *b; }
|
||||
@@ -155,9 +165,14 @@ namespace BlackMisc
|
||||
private:
|
||||
static int compareImpl(const Derived &a, const Derived &b)
|
||||
{
|
||||
constexpr auto meta = introspect<Derived>().without(MetaFlags<DisabledForComparison>());
|
||||
int result = baseCompare(static_cast<const TBaseOfT<Derived> *>(&a), static_cast<const TBaseOfT<Derived> *>(&b));
|
||||
meta.forEachMember([ & ](auto member) { result = result ? result : CompareByMetaClass::membersCompare(member.in(a), member.in(b), member.m_flags); });
|
||||
introspect<Derived>().forEachMember([ & ](auto member)
|
||||
{
|
||||
if constexpr (!decltype(member)::has(MetaFlags<DisabledForComparison>()))
|
||||
{
|
||||
result = result ? result : CompareByMetaClass::membersCompare(member.in(a), member.in(b), member.m_flags);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
template <typename T> static int baseCompare(const T *a, const T *b) { return compare(*a, *b); }
|
||||
|
||||
@@ -58,16 +58,26 @@ namespace BlackMisc
|
||||
void marshalToDataStream(QDataStream &stream) const
|
||||
{
|
||||
baseMarshal(static_cast<const TBaseOfT<Derived> *>(derived()), stream);
|
||||
constexpr auto meta = introspect<Derived>().without(MetaFlags<DisabledForMarshalling>());
|
||||
meta.forEachMember([ &, this ](auto member) { stream << member.in(*this->derived()); });
|
||||
introspect<Derived>().forEachMember([ &, this ](auto member)
|
||||
{
|
||||
if constexpr (!decltype(member)::has(MetaFlags<DisabledForMarshalling>()))
|
||||
{
|
||||
stream << member.in(*this->derived());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//! Unmarshal a value from a QDataStream.
|
||||
void unmarshalFromDataStream(QDataStream &stream)
|
||||
{
|
||||
baseUnmarshal(static_cast<TBaseOfT<Derived> *>(derived()), stream);
|
||||
constexpr auto meta = introspect<Derived>().without(MetaFlags<DisabledForMarshalling>());
|
||||
meta.forEachMember([ &, this ](auto member) { stream >> member.in(*this->derived()); });
|
||||
introspect<Derived>().forEachMember([ &, this ](auto member)
|
||||
{
|
||||
if constexpr (!decltype(member)::has(MetaFlags<DisabledForMarshalling>()))
|
||||
{
|
||||
stream >> member.in(*this->derived());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -71,19 +71,21 @@ namespace BlackMisc
|
||||
void marshallToDbus(QDBusArgument &arg, Tags...) const
|
||||
{
|
||||
baseMarshall(static_cast<const TBaseOfT<Derived> *>(derived()), arg);
|
||||
constexpr auto meta = introspect<Derived>().without(MetaFlags<DisabledForMarshalling>());
|
||||
meta.forEachMember([ &, this ](auto member)
|
||||
introspect<Derived>().forEachMember([ &, this ](auto member)
|
||||
{
|
||||
const auto &value = member.in(*this->derived());
|
||||
if constexpr (THasMarshallMethods<std::decay_t<decltype(value)>>::value)
|
||||
if constexpr (!decltype(member)::has(MetaFlags<DisabledForMarshalling>()))
|
||||
{
|
||||
if constexpr (member.has(MetaFlags<LosslessMarshalling>()))
|
||||
const auto &value = member.in(*this->derived());
|
||||
if constexpr (THasMarshallMethods<std::decay_t<decltype(value)>>::value)
|
||||
{
|
||||
value.marshallToDbus(arg, LosslessTag());
|
||||
if constexpr (member.has(MetaFlags<LosslessMarshalling>()))
|
||||
{
|
||||
value.marshallToDbus(arg, LosslessTag());
|
||||
}
|
||||
else { value.marshallToDbus(arg); }
|
||||
}
|
||||
else { value.marshallToDbus(arg); }
|
||||
else { arg << value; }
|
||||
}
|
||||
else { arg << value; }
|
||||
});
|
||||
}
|
||||
|
||||
@@ -91,19 +93,21 @@ namespace BlackMisc
|
||||
void unmarshallFromDbus(const QDBusArgument &arg, Tags...)
|
||||
{
|
||||
baseUnmarshall(static_cast<TBaseOfT<Derived> *>(derived()), arg);
|
||||
constexpr auto meta = introspect<Derived>().without(MetaFlags<DisabledForMarshalling>());
|
||||
meta.forEachMember([ &, this ](auto member)
|
||||
introspect<Derived>().forEachMember([ &, this ](auto member)
|
||||
{
|
||||
auto &value = member.in(*this->derived());
|
||||
if constexpr (THasMarshallMethods<std::decay_t<decltype(value)>>::value)
|
||||
if constexpr (!decltype(member)::has(MetaFlags<DisabledForMarshalling>()))
|
||||
{
|
||||
if constexpr (member.has(MetaFlags<LosslessMarshalling>()))
|
||||
auto &value = member.in(*this->derived());
|
||||
if constexpr (THasMarshallMethods<std::decay_t<decltype(value)>>::value)
|
||||
{
|
||||
value.unmarshallFromDbus(arg, LosslessTag());
|
||||
if constexpr (member.has(MetaFlags<LosslessMarshalling>()))
|
||||
{
|
||||
value.unmarshallFromDbus(arg, LosslessTag());
|
||||
}
|
||||
else { value.unmarshallFromDbus(arg); }
|
||||
}
|
||||
else { value.unmarshallFromDbus(arg); }
|
||||
else { arg >> value; }
|
||||
}
|
||||
else { arg >> value; }
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -60,8 +60,13 @@ namespace BlackMisc
|
||||
static uint hashImpl(const Derived &value)
|
||||
{
|
||||
uint hash = baseHash(static_cast<const TBaseOfT<Derived> *>(&value));
|
||||
constexpr auto meta = introspect<Derived>().without(MetaFlags<DisabledForHashing>());
|
||||
meta.forEachMember([ & ](const auto &member) { hash ^= qHash(member.in(value)); });
|
||||
introspect<Derived>().forEachMember([ & ](auto member)
|
||||
{
|
||||
if constexpr (!decltype(member)::has(MetaFlags<DisabledForHashing>()))
|
||||
{
|
||||
hash ^= qHash(member.in(value));
|
||||
}
|
||||
});
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
@@ -96,10 +96,12 @@ namespace BlackMisc
|
||||
QJsonObject toJson() const
|
||||
{
|
||||
QJsonObject json;
|
||||
constexpr auto meta = introspect<Derived>().without(MetaFlags<DisabledForJson>());
|
||||
meta.forEachMember([ &, this ](auto member)
|
||||
introspect<Derived>().forEachMember([ &, this ](auto member)
|
||||
{
|
||||
json << std::make_pair(CExplicitLatin1String(member.latin1Name()), std::cref(member.in(*this->derived())));
|
||||
if constexpr (!decltype(member)::has(MetaFlags<DisabledForJson>()))
|
||||
{
|
||||
json << std::make_pair(CExplicitLatin1String(member.latin1Name()), std::cref(member.in(*this->derived())));
|
||||
}
|
||||
});
|
||||
return Json::appendJsonObject(json, baseToJson(static_cast<const TBaseOfT<Derived> *>(derived())));
|
||||
}
|
||||
@@ -115,23 +117,25 @@ namespace BlackMisc
|
||||
void convertFromJson(const QJsonObject &json)
|
||||
{
|
||||
baseConvertFromJson(static_cast<TBaseOfT<Derived> *>(derived()), json);
|
||||
constexpr auto meta = introspect<Derived>().without(MetaFlags<DisabledForJson>());
|
||||
meta.forEachMember([ &, this ](auto member)
|
||||
introspect<Derived>().forEachMember([ &, this ](auto member)
|
||||
{
|
||||
const auto value = json.value(CExplicitLatin1String(member.latin1Name()));
|
||||
if (value.isUndefined())
|
||||
if constexpr (!decltype(member)::has(MetaFlags<DisabledForJson>()))
|
||||
{
|
||||
constexpr bool required = false; //! \fixme add RequiredForJson flag in metaclass system
|
||||
// cppcheck-suppress knownConditionTrueFalse
|
||||
// QLatin1String used instead of QStringLiteral below since the latter causes an internal compiler bug
|
||||
// in GCC 8 and higher
|
||||
if (required) { throw CJsonException(QLatin1String("Missing required member '%1'").arg(member.latin1Name())); }
|
||||
}
|
||||
else
|
||||
{
|
||||
CJsonScope scope(member.latin1Name());
|
||||
Q_UNUSED(scope);
|
||||
value >> member.in(*this->derived());
|
||||
const auto value = json.value(CExplicitLatin1String(member.latin1Name()));
|
||||
if (value.isUndefined())
|
||||
{
|
||||
constexpr bool required = false; //! \fixme add RequiredForJson flag in metaclass system
|
||||
// cppcheck-suppress knownConditionTrueFalse
|
||||
// QLatin1String used instead of QStringLiteral below since the latter causes an internal compiler bug
|
||||
// in GCC 8 and higher
|
||||
if (required) { throw CJsonException(QLatin1String("Missing required member '%1'").arg(member.latin1Name())); }
|
||||
}
|
||||
else
|
||||
{
|
||||
CJsonScope scope(member.latin1Name());
|
||||
Q_UNUSED(scope);
|
||||
value >> member.in(*this->derived());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -125,22 +125,26 @@ namespace BlackMisc
|
||||
QJsonObject CAircraftModel::toMemoizedJson(MemoHelper::CMemoizer &helper) const
|
||||
{
|
||||
QJsonObject json;
|
||||
constexpr auto meta = introspect<CAircraftModel>().without(MetaFlags<DisabledForJson>());
|
||||
meta.forEachMember([ &, this ](auto member)
|
||||
introspect<CAircraftModel>().forEachMember([ &, this ](auto member)
|
||||
{
|
||||
auto &&maybeMemo = helper.maybeMemoize(member.in(*this));
|
||||
json << std::make_pair(CExplicitLatin1String(member.latin1Name()), std::cref(maybeMemo));
|
||||
if constexpr (!decltype(member)::has(MetaFlags<DisabledForJson>()))
|
||||
{
|
||||
auto &&maybeMemo = helper.maybeMemoize(member.in(*this));
|
||||
json << std::make_pair(CExplicitLatin1String(member.latin1Name()), std::cref(maybeMemo));
|
||||
}
|
||||
});
|
||||
return json;
|
||||
}
|
||||
|
||||
void CAircraftModel::convertFromMemoizedJson(const QJsonObject &json, const MemoHelper::CUnmemoizer &helper)
|
||||
{
|
||||
constexpr auto meta = introspect<CAircraftModel>().without(MetaFlags<DisabledForJson>());
|
||||
meta.forEachMember([ &, this ](auto member)
|
||||
introspect<CAircraftModel>().forEachMember([ &, this ](auto member)
|
||||
{
|
||||
auto it = json.find(CExplicitLatin1String(member.latin1Name()));
|
||||
if (it != json.end()) { it.value() >> helper.maybeUnmemoize(member.in(*this)).get(); }
|
||||
if constexpr (!decltype(member)::has(MetaFlags<DisabledForJson>()))
|
||||
{
|
||||
auto it = json.find(CExplicitLatin1String(member.latin1Name()));
|
||||
if (it != json.end()) { it.value() >> helper.maybeUnmemoize(member.in(*this)).get(); }
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user