mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-18 03:15:34 +08:00
refs #245 & #210 with proper variadic templates we can use index_sequence to simplify some of the recursion in the tuple system
This commit is contained in:
@@ -181,7 +181,7 @@ namespace BlackMisc
|
|||||||
template <class... Ts>
|
template <class... Ts>
|
||||||
int compare(std::tuple<Ts...> a, std::tuple<Ts...> b)
|
int compare(std::tuple<Ts...> a, std::tuple<Ts...> b)
|
||||||
{
|
{
|
||||||
return Private::TupleHelper<sizeof...(Ts)>::compare(a, b);
|
return Private::TupleHelper::compare(a, b, Private::make_index_sequence<sizeof...(Ts)>());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -191,7 +191,7 @@ namespace BlackMisc
|
|||||||
template <class... Ts>
|
template <class... Ts>
|
||||||
QDBusArgument &operator <<(QDBusArgument &arg, std::tuple<Ts...> tu)
|
QDBusArgument &operator <<(QDBusArgument &arg, std::tuple<Ts...> tu)
|
||||||
{
|
{
|
||||||
return Private::TupleHelper<sizeof...(Ts)>::marshall(arg, tu);
|
return Private::TupleHelper::marshall(arg, tu, Private::make_index_sequence<sizeof...(Ts)>());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -201,7 +201,7 @@ namespace BlackMisc
|
|||||||
template <class... Ts>
|
template <class... Ts>
|
||||||
const QDBusArgument &operator >>(const QDBusArgument &arg, std::tuple<Ts...> tu)
|
const QDBusArgument &operator >>(const QDBusArgument &arg, std::tuple<Ts...> tu)
|
||||||
{
|
{
|
||||||
return Private::TupleHelper<sizeof...(Ts)>::unmarshall(arg, tu);
|
return Private::TupleHelper::unmarshall(arg, tu, Private::make_index_sequence<sizeof...(Ts)>());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -211,7 +211,7 @@ namespace BlackMisc
|
|||||||
template <class... Ts>
|
template <class... Ts>
|
||||||
QDebug operator <<(QDebug debug, std::tuple<Ts &...> tu)
|
QDebug operator <<(QDebug debug, std::tuple<Ts &...> tu)
|
||||||
{
|
{
|
||||||
return Private::TupleHelper<sizeof...(Ts)>::debug(debug, tu);
|
return Private::TupleHelper::debug(debug, tu, Private::make_index_sequence<sizeof...(Ts)>());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -232,7 +232,7 @@ namespace BlackMisc
|
|||||||
template <class... Ts>
|
template <class... Ts>
|
||||||
uint qHash(std::tuple<Ts...> tu)
|
uint qHash(std::tuple<Ts...> tu)
|
||||||
{
|
{
|
||||||
return Private::TupleHelper<sizeof...(Ts)>::hash(tu);
|
return Private::TupleHelper::hash(tu, Private::make_index_sequence<sizeof...(Ts)>());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -243,7 +243,7 @@ namespace BlackMisc
|
|||||||
QJsonObject serializeJson(const QStringList &members, std::tuple<Ts...> tu)
|
QJsonObject serializeJson(const QStringList &members, std::tuple<Ts...> tu)
|
||||||
{
|
{
|
||||||
QJsonObject json;
|
QJsonObject json;
|
||||||
Private::TupleHelper<sizeof...(Ts)>::serializeJson(json, members, tu);
|
Private::TupleHelper::serializeJson(json, members, tu, Private::make_index_sequence<sizeof...(Ts)>());
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -254,7 +254,7 @@ namespace BlackMisc
|
|||||||
template <class... Ts>
|
template <class... Ts>
|
||||||
void deserializeJson(const QJsonObject &json, const QStringList &members, std::tuple<Ts...> tu)
|
void deserializeJson(const QJsonObject &json, const QStringList &members, std::tuple<Ts...> tu)
|
||||||
{
|
{
|
||||||
Private::TupleHelper<sizeof...(Ts)>::deserializeJson(json, members, tu);
|
Private::TupleHelper::deserializeJson(json, members, tu, Private::make_index_sequence<sizeof...(Ts)>());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace BlackMisc
|
} // namespace BlackMisc
|
||||||
|
|||||||
@@ -73,6 +73,29 @@ namespace BlackMisc
|
|||||||
}
|
}
|
||||||
//! @}
|
//! @}
|
||||||
|
|
||||||
|
// Our own implementation of std::index_sequence (because not implemented by MSVC2013)
|
||||||
|
//! \private
|
||||||
|
//! @{
|
||||||
|
template <size_t... Is>
|
||||||
|
struct index_sequence
|
||||||
|
{
|
||||||
|
static const size_t size = sizeof...(Is);
|
||||||
|
typedef std::tuple<std::integral_constant<size_t, Is>...> tuple_type;
|
||||||
|
};
|
||||||
|
template <size_t I, size_t C, size_t... Is>
|
||||||
|
struct GenSequence
|
||||||
|
{
|
||||||
|
typedef typename GenSequence<I + 1, C, Is..., I>::type type;
|
||||||
|
};
|
||||||
|
template <size_t C, size_t... Is>
|
||||||
|
struct GenSequence<C, C, Is...>
|
||||||
|
{
|
||||||
|
typedef index_sequence<Is...> type;
|
||||||
|
};
|
||||||
|
template <size_t C>
|
||||||
|
using make_index_sequence = typename GenSequence<0, C>::type;
|
||||||
|
//! @}
|
||||||
|
|
||||||
// Helper which will allow us to hook in our own customizations into BlackMisc::tie
|
// Helper which will allow us to hook in our own customizations into BlackMisc::tie
|
||||||
//! \private
|
//! \private
|
||||||
//! @{
|
//! @{
|
||||||
@@ -83,76 +106,115 @@ namespace BlackMisc
|
|||||||
}
|
}
|
||||||
//! @}
|
//! @}
|
||||||
|
|
||||||
// Applying operations to all elements in a tuple, using recursion
|
// Applying operations to all elements in a tuple, using index_sequence instead of recursion
|
||||||
//! \private
|
//! \private
|
||||||
template <int N>
|
class TupleHelper
|
||||||
struct TupleHelper
|
|
||||||
{
|
{
|
||||||
template <class Tu>
|
public:
|
||||||
static int compare(const Tu &a, const Tu &b)
|
template <class Tu, size_t... Is>
|
||||||
|
static int compare(const Tu &a, const Tu &b, index_sequence<Is...>)
|
||||||
{
|
{
|
||||||
const int head = TupleHelper < N - 1 >::compare(a, b);
|
return compareImpl(std::make_pair(get_ref<Is>(a), get_ref<Is>(b))...);
|
||||||
if (head) { return head; }
|
|
||||||
return compareHelper < N - 1 > (a, b);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Tu>
|
template <class Tu, size_t... Is>
|
||||||
static QDBusArgument &marshall(QDBusArgument &arg, const Tu &tu)
|
static QDBusArgument &marshall(QDBusArgument &arg, const Tu &tu, index_sequence<Is...>)
|
||||||
{
|
{
|
||||||
return TupleHelper < N - 1 >::marshall(arg, tu) << std::get < N - 1 > (tu);
|
marshallImpl(arg, std::get<Is>(tu)...);
|
||||||
|
return arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Tu>
|
template <class Tu, size_t... Is>
|
||||||
static const QDBusArgument &unmarshall(const QDBusArgument &arg, Tu &tu)
|
static const QDBusArgument &unmarshall(const QDBusArgument &arg, Tu &tu, index_sequence<Is...>)
|
||||||
{
|
{
|
||||||
return TupleHelper < N - 1 >::unmarshall(arg, tu) >> std::get < N - 1 > (tu);
|
unmarshallImpl(arg, std::get<Is>(tu)...);
|
||||||
|
return arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Tu>
|
template <class Tu, size_t... Is>
|
||||||
static QDebug debug(QDebug dbg, Tu &tu)
|
static QDebug debug(QDebug dbg, const Tu &tu, index_sequence<Is...>)
|
||||||
{
|
{
|
||||||
return TupleHelper < N - 1 >::debug(dbg, tu) << std::get < N - 1 > (tu);
|
debugImpl(dbg, std::get<Is>(tu)...);
|
||||||
|
return dbg;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Tu>
|
template <class Tu, size_t... Is>
|
||||||
static uint hash(const Tu &tu)
|
static uint hash(const Tu &tu, index_sequence<Is...>)
|
||||||
{
|
{
|
||||||
return TupleHelper < N - 1 >::hash(tu) ^ qHash(std::get < N - 1 > (tu));
|
return hashImpl(qHash(std::get<Is>(tu))...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Tu>
|
template <class Tu, size_t... Is>
|
||||||
static void serializeJson(QJsonObject &json, const QStringList &members, const Tu &tu)
|
static void serializeJson(QJsonObject &json, const QStringList &names, const Tu &tu, index_sequence<Is...>)
|
||||||
{
|
{
|
||||||
TupleHelper < N - 1 >::serializeJson(json, members, tu);
|
serializeJsonImpl(json, std::make_pair(names[Is], std::get<Is>(tu))...);
|
||||||
json << std::make_pair(members.at(N - 1), std::get < N - 1 >(tu));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Tu>
|
template <class Tu, size_t... Is>
|
||||||
static void deserializeJson(const QJsonObject &json, const QStringList &members, Tu &tu)
|
static void deserializeJson(const QJsonObject &json, const QStringList &names, Tu &tu, index_sequence<Is...>)
|
||||||
{
|
{
|
||||||
TupleHelper < N - 1 >::deserializeJson(json, members, tu);
|
deserializeJsonImpl(json, std::make_pair(names[Is], get_ref<Is>(tu))...);
|
||||||
json.value(members.at(N - 1)) >> std::get < N - 1 >(tu);
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
//! \private
|
private:
|
||||||
template <>
|
template <size_t I, class T>
|
||||||
struct TupleHelper<0>
|
static auto get_ref(T &&tu) -> decltype(std::ref(std::get<I>(std::forward<T>(tu))))
|
||||||
{
|
{
|
||||||
template <class Tu>
|
return std::ref(std::get<I>(std::forward<T>(tu)));
|
||||||
static int compare(const Tu &, const Tu &) { return 0; }
|
}
|
||||||
template <class Tu>
|
|
||||||
static QDBusArgument &marshall(QDBusArgument &arg, const Tu &) { return arg; }
|
static int compareImpl() { return 0; }
|
||||||
template <class Tu>
|
template <class T, class... Ts>
|
||||||
static const QDBusArgument &unmarshall(const QDBusArgument &arg, Tu &) { return arg; }
|
static int compareImpl(const std::pair<T, T> &head, const Ts &... tail)
|
||||||
template <class Tu>
|
{
|
||||||
static QDebug debug(QDebug dbg, Tu &) { return dbg; }
|
int result = compareHelper(head.first, head.second, typename std::is_base_of<CValueObject, typename std::decay<T>::type>::type());
|
||||||
template <class Tu>
|
if (result) return result;
|
||||||
static uint hash(const Tu &) { return 0; }
|
return compareImpl(tail...);
|
||||||
template <class Tu>
|
}
|
||||||
static void serializeJson(QJsonObject &, const QStringList &, const Tu &) {}
|
|
||||||
template <class Tu>
|
static void marshallImpl(QDBusArgument &) {}
|
||||||
static void deserializeJson(const QJsonObject &, const QStringList &, Tu &) {}
|
template <class T, class... Ts>
|
||||||
|
static void marshallImpl(QDBusArgument &arg, const T &head, const Ts &... tail)
|
||||||
|
{
|
||||||
|
arg << head;
|
||||||
|
marshallImpl(arg, tail...);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void unmarshallImpl(const QDBusArgument &) {}
|
||||||
|
template <class T, class... Ts>
|
||||||
|
static void unmarshallImpl(const QDBusArgument &arg, T &head, Ts &... tail)
|
||||||
|
{
|
||||||
|
arg >> head;
|
||||||
|
unmarshallImpl(arg, tail...);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void debugImpl(QDebug) {}
|
||||||
|
template <class T, class... Ts>
|
||||||
|
static void debugImpl(QDebug dbg, const T &head, const Ts &... tail)
|
||||||
|
{
|
||||||
|
dbg << head;
|
||||||
|
debugImpl(dbg, tail...);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void serializeJsonImpl(QJsonObject &) {}
|
||||||
|
template <class T, class... Ts>
|
||||||
|
static void serializeJsonImpl(QJsonObject &json, std::pair<QString, T> head, Ts... tail)
|
||||||
|
{
|
||||||
|
json << head;
|
||||||
|
serializeJsonImpl(json, tail...);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void deserializeJsonImpl(const QJsonObject &) {}
|
||||||
|
template <class T, class... Ts>
|
||||||
|
static void deserializeJsonImpl(const QJsonObject &json, std::pair<QString, T> head, Ts... tail)
|
||||||
|
{
|
||||||
|
json.value(head.first) >> head.second;
|
||||||
|
deserializeJsonImpl(json, tail...);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint hashImpl() { return 0; }
|
||||||
|
template <class... Ts>
|
||||||
|
static uint hashImpl(uint head, Ts... tail) { return head ^ hashImpl(tail...); }
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Private
|
} // namespace Private
|
||||||
|
|||||||
Reference in New Issue
Block a user