diff --git a/src/blackmisc/avairporticao.cpp b/src/blackmisc/avairporticao.cpp index a4c13f223..a7d7958d4 100644 --- a/src/blackmisc/avairporticao.cpp +++ b/src/blackmisc/avairporticao.cpp @@ -27,7 +27,7 @@ namespace BlackMisc int CAirportIcao::compareImpl(const CValueObject &otherBase) const { const auto &other = static_cast(otherBase); - return this->m_icaoCode.compare(other.m_icaoCode, Qt::CaseInsensitive); + return compare(TupleConverter::toMetaTuple(*this), TupleConverter::toMetaTuple(other)); } /* @@ -96,7 +96,7 @@ namespace BlackMisc bool CAirportIcao::operator ==(const CAirportIcao &other) const { if (this == &other) return true; - return this->asString().compare(other.asString(), Qt::CaseInsensitive) == 0; + return TupleConverter::toMetaTuple(*this) == TupleConverter::toMetaTuple(other); } /* diff --git a/src/blackmisc/avairporticao.h b/src/blackmisc/avairporticao.h index fecf1d2c0..c2b19db68 100644 --- a/src/blackmisc/avairporticao.h +++ b/src/blackmisc/avairporticao.h @@ -106,7 +106,9 @@ namespace BlackMisc } // namespace } // namespace -BLACK_DECLARE_TUPLE_CONVERSION(BlackMisc::Aviation::CAirportIcao, (o.m_icaoCode)) +BLACK_DECLARE_TUPLE_CONVERSION(BlackMisc::Aviation::CAirportIcao, ( + attr(o.m_icaoCode, flags()) +)) Q_DECLARE_METATYPE(BlackMisc::Aviation::CAirportIcao) #endif // guard diff --git a/src/blackmisc/avcallsign.cpp b/src/blackmisc/avcallsign.cpp index edd904de9..c36962165 100644 --- a/src/blackmisc/avcallsign.cpp +++ b/src/blackmisc/avcallsign.cpp @@ -85,7 +85,7 @@ namespace BlackMisc int CCallsign::compareImpl(const CValueObject &otherBase) const { const auto &other = static_cast(otherBase); - return this->m_callsign.compare(other.m_callsign, Qt::CaseInsensitive); + return compare(TupleConverter::toMetaTuple(*this), TupleConverter::toMetaTuple(other)); } /* @@ -181,7 +181,7 @@ namespace BlackMisc bool CCallsign::operator ==(const CCallsign &other) const { if (this == &other) return true; - return this->asString().compare(other.asString(), Qt::CaseInsensitive) == 0; + return TupleConverter::toMetaTuple(*this) == TupleConverter::toMetaTuple(other); } /* diff --git a/src/blackmisc/avcallsign.h b/src/blackmisc/avcallsign.h index 2ebc9a82f..2d6ccd50a 100644 --- a/src/blackmisc/avcallsign.h +++ b/src/blackmisc/avcallsign.h @@ -139,7 +139,11 @@ namespace BlackMisc } // namespace } // namespace -BLACK_DECLARE_TUPLE_CONVERSION(BlackMisc::Aviation::CCallsign, (o.m_callsign, o.m_callsignAsSet, o.m_telephonyDesignator)) +BLACK_DECLARE_TUPLE_CONVERSION(BlackMisc::Aviation::CCallsign, ( + attr(o.m_callsign, flags()), + attr(o.m_callsignAsSet, flags()), + attr(o.m_telephonyDesignator, flags()) +)) Q_DECLARE_METATYPE(BlackMisc::Aviation::CCallsign) #endif // guard diff --git a/src/blackmisc/tuple.h b/src/blackmisc/tuple.h index b51c232e9..ee16e5a18 100644 --- a/src/blackmisc/tuple.h +++ b/src/blackmisc/tuple.h @@ -26,7 +26,8 @@ namespace BlackMisc DisabledForMarshalling = 1 << 1, //!< Element will be ignored during DBus marshalling DisabledForDebugging = 1 << 2, //!< Element will be ignored when streaming to QDebug DisabledForHashing = 1 << 3, //!< Element will be ignored by qHash() - DisabledForJson = 1 << 4 //!< Element will be ignored during JSON serialization + DisabledForJson = 1 << 4, //!< Element will be ignored during JSON serialization + CaseInsensitiveComparison = 1 << 5 //!< Element will be compared case insensitively (must be a QString) }; } @@ -305,10 +306,9 @@ namespace BlackMisc template int compare(std::tuple a, std::tuple b) { - auto valuesA = Private::stripMeta(a, Private::make_index_sequence()); - auto valuesB = Private::stripMeta(b, Private::make_index_sequence()); - auto metaTu = Private::recoverMeta(a, Private::make_index_sequence()); - return Private::TupleHelper::compare(valuesA, valuesB, Private::skipFlaggedIndices(metaTu)); + auto metaA = Private::recoverMeta(a, Private::make_index_sequence()); + auto metaB = Private::recoverMeta(b, Private::make_index_sequence()); + return Private::TupleHelper::compare_(metaA, metaB, Private::skipFlaggedIndices(metaA)); } /*! diff --git a/src/blackmisc/tuple_private.h b/src/blackmisc/tuple_private.h index 7048b41b2..b0937eccc 100644 --- a/src/blackmisc/tuple_private.h +++ b/src/blackmisc/tuple_private.h @@ -116,9 +116,47 @@ namespace BlackMisc return {}; } + // CRTP base class for Attribute, to select appropriate method of comparison. + template + struct AttributeComparable; + template + struct AttributeComparable + { + friend int compare(const Derived &, const Derived &) { return 0; } + friend bool operator ==(const Derived &, const Derived &) { return true; } + friend bool operator !=(const Derived &, const Derived &) { return false; } + friend bool operator <(const Derived &, const Derived &) { return false; } + friend bool operator <=(const Derived &, const Derived &) { return true; } + friend bool operator >(const Derived &, const Derived &) { return false; } + friend bool operator >=(const Derived &, const Derived &) { return true; } + }; + template + struct AttributeComparable + { + template using isCValueObject = typename std::is_base_of::type; + friend int compare(const Derived &a, const Derived &b) { return compareHelper(a.m_obj, b.m_obj, isCValueObject()); } + friend bool operator ==(const Derived &a, const Derived &b) { return a.m_obj == b.m_obj; } + friend bool operator !=(const Derived &a, const Derived &b) { return a.m_obj != b.m_obj; } + friend bool operator <(const Derived &a, const Derived &b) { return a.m_obj < b.m_obj; } + friend bool operator <=(const Derived &a, const Derived &b) { return a.m_obj <= b.m_obj; } + friend bool operator >(const Derived &a, const Derived &b) { return a.m_obj > b.m_obj; } + friend bool operator >=(const Derived &a, const Derived &b) { return a.m_obj >= b.m_obj; } + }; + template + struct AttributeComparable + { + friend int compare(const Derived &a, const Derived &b) { return a.m_obj.compare(b.m_obj, Qt::CaseInsensitive); } + friend bool operator ==(const Derived &a, const Derived &b) { return a.m_obj.compare(b.m_obj, Qt::CaseInsensitive) == 0; } + friend bool operator !=(const Derived &a, const Derived &b) { return a.m_obj.compare(b.m_obj, Qt::CaseInsensitive) != 0; } + friend bool operator <(const Derived &a, const Derived &b) { return a.m_obj.compare(b.m_obj, Qt::CaseInsensitive) < 0; } + friend bool operator <=(const Derived &a, const Derived &b) { return a.m_obj.compare(b.m_obj, Qt::CaseInsensitive) <= 0; } + friend bool operator >(const Derived &a, const Derived &b) { return a.m_obj.compare(b.m_obj, Qt::CaseInsensitive) > 0; } + friend bool operator >=(const Derived &a, const Derived &b) { return a.m_obj.compare(b.m_obj, Qt::CaseInsensitive) >= 0; } + }; + // A tuple element with attached metadata. template - struct Attribute + struct Attribute : public AttributeComparable, Flags & DisabledForComparison, Flags & CaseInsensitiveComparison> { typedef T type; static const qint64 flags = Flags; @@ -127,13 +165,6 @@ namespace BlackMisc void extend(QString jsonName) { if (m_jsonName.isEmpty()) m_jsonName = jsonName; } T &m_obj; QString m_jsonName; - - friend bool operator ==(const Attribute &a, const Attribute &b) { return a.m_obj == b.m_obj; } - friend bool operator !=(const Attribute &a, const Attribute &b) { return a.m_obj != b.m_obj; } - friend bool operator <(const Attribute &a, const Attribute &b) { return a.m_obj < b.m_obj; } - friend bool operator <=(const Attribute &a, const Attribute &b) { return a.m_obj <= b.m_obj; } - friend bool operator >(const Attribute &a, const Attribute &b) { return a.m_obj > b.m_obj; } - friend bool operator >=(const Attribute &a, const Attribute &b) { return a.m_obj >= b.m_obj; } }; // Helpers used in tie(), tieMeta(), and elsewhere, which arrange for the correct types to be passed to std::make_tuple. @@ -193,9 +224,9 @@ namespace BlackMisc { public: template - static int compare(const Tu &a, const Tu &b, index_sequence) + static int compare_(const Tu &a, const Tu &b, index_sequence) // underscore to avoid hiding the name "compare" in other scopes { - return compareImpl(std::make_pair(get_ref(a), get_ref(b))...); + return compareImpl(std::make_pair(std::get(a), std::get(b))...); } template @@ -260,7 +291,7 @@ namespace BlackMisc template static int compareImpl(const std::pair &head, const Ts &... tail) { - int result = compareHelper(head.first, head.second, typename std::is_base_of::type>::type()); + int result = compare(head.first, head.second); if (result) return result; return compareImpl(tail...); }