Quello che hai fatto di sbagliato è stato qui:
using type = typename tuple_reverse<
std::tuple<
typename tuple_reverse<std::tuple<Ts..., T>>::type
>
>::type;
Guardando la cosa dal di dentro, è riordinare gli elementi tuple: tuple<Ts..., T>
, quindi si tenta di invertire tale, allora si mette il risultato in un tuple
, allora provi a rovesciare che ... eh ?! :)
Ciò significa che ogni volta che si crea un'istanza di tuple_reverse
si ottiene una tupla delle stesse dimensioni, quindi non finisce mai e si ricorpora in modo ricorsivo per sempre. (Quindi, se quella ricorsione è finita, metti il tipo di tupla risultante in una tupla, quindi hai una tupla a elemento singolo che contiene una tupla di elementi N, e rovescia quella, che non fa nulla perché l'inversione di una tupla a elemento singolo è un no-op)
si vuole staccare uno degli elementi, poi invertire il resto, e concatenare nuovo indietro:.
using head = std::tuple<T>;
using tail = typename tuple_reverse<std::tuple<Ts...>>::type;
using type = decltype(std::tuple_cat(std::declval<tail>(), std::declval<head>()));
e non c'è bisogno di avvolgerlo in una tupla e invertire di nuovo :)
E si dovrebbe anche gestire il caso tupla vuota, quindi il tutto è:
template <typename... Ts>
struct tuple_reverse;
template <>
struct tuple_reverse<std::tuple<>>
{
using type = std::tuple<>;
};
template <typename T, typename... Ts>
struct tuple_reverse<std::tuple<T, Ts...>>
{
using head = std::tuple<T>;
using tail = typename tuple_reverse<std::tuple<Ts...>>::type;
using type = decltype(std::tuple_cat(std::declval<tail>(), std::declval<head>()));
};
Lo farei diversamente però.
per ottenere solo il tipo, utilizzando C++ 14
template<typename T, size_t... I>
struct tuple_reverse_impl<T, std::index_sequence<I...>>
{
typedef std::tuple<typename std::tuple_element<sizeof...(I) - 1 - I, T>::type...> type;
};
// partial specialization for handling empty tuples:
template<typename T>
struct tuple_reverse_impl<T, std::index_sequence<>>
{
typedef T type;
};
template<typename T>
struct tuple_reverse<T>
: tuple_reverse_impl<T, std::make_index_sequence<std::tuple_size<T>::value>>
{ };
Oppure si può scrivere una funzione per invertire un oggetto tupla vero e proprio, quindi utilizzare decltype(reverse(t))
per ottenere il tipo.Per invertire un oggetto tupla simile in C++ 14:
template<typename T, size_t... I>
auto
reverse_impl(T&& t, std::index_sequence<I...>)
{
return std::make_tuple(std::get<sizeof...(I) - 1 - I>(std::forward<T>(t))...);
}
template<typename T>
auto
reverse(T&& t)
{
return reverse_impl(std::forward<T>(t),
std::make_index_sequence<std::tuple_size<T>::value>());
}
In C++ 11 uso <integer_seq.h>
e aggiungere tipi di ritorno e utilizzare remove_reference
spogliare riferimenti del tipo tupla (perché tuple_size
e tuple_element
non funzionano con riferimenti alle tuple):
template<typename T, typename TT = typename std::remove_reference<T>::type, size_t... I>
auto
reverse_impl(T&& t, redi::index_sequence<I...>)
-> std::tuple<typename std::tuple_element<sizeof...(I) - 1 - I, TT>::type...>
{
return std::make_tuple(std::get<sizeof...(I) - 1 - I>(std::forward<T>(t))...);
}
template<typename T, typename TT = typename std::remove_reference<T>::type>
auto
reverse(T&& t)
-> decltype(reverse_impl(std::forward<T>(t),
redi::make_index_sequence<std::tuple_size<TT>::value>()))
{
return reverse_impl(std::forward<T>(t),
redi::make_index_sequence<std::tuple_size<TT>::value>());
}
non credo che avete bisogno di ricorsione di fare questo, [tuple_cat] (http://www.cplusplus.com/reference/tuple/tuple_cat/), ma perché si vuole invertire una tupla – aaronman