/* Copyright (C) 2014 VATSIM Community / authors * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*! \file Private implementation details used by tuple.h */ #ifndef BLACKMISC_TUPLE_PRIVATE_H #define BLACKMISC_TUPLE_PRIVATE_H #include "json.h" #include #include #include #include #include #include #include #include namespace BlackMisc { class CValueObject; namespace Private { // Using SFINAE to help detect missing BLACK_ENABLE_TUPLE_CONVERSION macro in static_assert //! \private std::false_type hasEnabledTupleConversionHelper(...); //! \private template typename T::EnabledTupleConversion hasEnabledTupleConversionHelper(T *); //! \private template struct HasEnabledTupleConversion { typedef decltype(hasEnabledTupleConversionHelper(static_cast(nullptr))) type; static const bool value = type::value; }; // Using tag dispatch to select which implementation of compare() to use //! \private //! @{ template int compareHelper(const T &a, const T &b, std::true_type isCValueObjectTag) { Q_UNUSED(isCValueObjectTag); return compare(a, b); } template int compareHelper(const T &a, const T &b, std::false_type isCValueObjectTag) { Q_UNUSED(isCValueObjectTag); if (a < b) { return -1; } if (a > b) { return 1; } return 0; } template int compareHelper(const Tu &a, const Tu &b) { typedef typename std::is_base_of < CValueObject, typename std::decay < typename std::tuple_element::type >::type >::type isCValueObjectTag; return compareHelper(std::get(a), std::get(b), isCValueObjectTag()); } //! @} #ifdef Q_COMPILER_VARIADIC_TEMPLATES // Applying operations to all elements in a tuple, using recursion //! \private template struct TupleHelper { template static int compare(const Tu &a, const Tu &b) { const int head = TupleHelper < N - 1 >::compare(a, b); if (head) { return head; } return compareHelper < N - 1 > (a, b); } template static QDBusArgument &marshall(QDBusArgument &arg, const Tu &tu) { return TupleHelper < N - 1 >::marshall(arg, tu) << std::get < N - 1 > (tu); } template static const QDBusArgument &unmarshall(const QDBusArgument &arg, Tu &tu) { return TupleHelper < N - 1 >::unmarshall(arg, tu) >> std::get < N - 1 > (tu); } template static uint hash(const Tu &tu) { return TupleHelper < N - 1 >::hash(tu) ^ qHash(std::get < N - 1 > (tu)); } template static void serializeJson(QJsonObject &json, const QStringList &members, const Tu &tu) { json << std::make_pair(members.at(N - 1), std::get < N - 1 > (tu)); TupleHelper < N - 1 >::serializeJson(json, members, tu); } template static void deserializeJson(const QJsonObject &json, const QStringList &members, Tu &tu) { json.value(members.at(N - 1)) >> std::get < N - 1 > (tu); TupleHelper < N - 1 >::deserializeJson(json, members, tu); } }; //! \private template <> struct TupleHelper<0> { template static int compare(const Tu &, const Tu &) { return 0; } template static QDBusArgument &marshall(QDBusArgument &arg, const Tu &) { return arg; } template static const QDBusArgument &unmarshall(const QDBusArgument &arg, Tu &) { return arg; } template static uint hash(const Tu &) { return 0; } template static void serializeJson(QJsonObject &, const QStringList &, const Tu &) {} template static void deserializeJson(const QJsonObject &, const QStringList &, Tu &) {} }; #endif // Q_COMPILER_VARIADIC_TEMPLATES } // namespace Private } // namespace BlackMisc #endif // guard