如何反转元组类型中元素类型的顺序?
如何反转元组中的类型?例如,我希望 reverse_tuple< std :: tuple< int,char,bool> :: type
是 std :: tuple< bool ,char,int>
。我尝试了以下操作,但没有成功。我做错了什么?
How do I reverse the types in a tuple? For example, I want reverse_tuple<std::tuple<int, char, bool>>::type
to be std::tuple<bool, char, int>
. I tried doing the following but it didn't work. What did I do wrong?
#include <type_traits>
#include <tuple>
template <typename... Ts>
struct tuple_reverse;
template <typename T, typename... Ts>
struct tuple_reverse<std::tuple<T, Ts...>>
{
using type = typename tuple_reverse<
std::tuple<
typename tuple_reverse<std::tuple<Ts..., T>>::type
>
>::type;
};
template <typename T>
struct tuple_reverse<std::tuple<T>>
{
using type = std::tuple<T>;
};
int main()
{
using result_type = std::tuple<int, bool, char>;
static_assert(
std::is_same<
tuple_reverse<var>::type, std::tuple<char, bool, int>
>::value, ""
);
}
这是我的错误:
prog.cpp:实例化'struct tuple_reverse< std :: tuple< ; char,int,bool> >:
prog.cpp:15:34:从struct tuple_reverse< std :: tuple< bool,char,int>中递归要求>’$ c>
prog.cpp:15:34:来自struct tuple_reverse< std :: tuple< int,bool,char> >'
prog.cpp:29:31:从此处开始$ c>
prog.cpp:15:34:错误:在'struct tuple_reverse< std :: tuple< int,bool,char>中没有名为'type'的类型>'
prog.cpp:在函数'int main()'中:
prog.cpp:30:9:错误:模板参数1无效
您在这里做错了:
using type = typename tuple_reverse<
std::tuple<
typename tuple_reverse<std::tuple<Ts..., T>>::type
>
>::type;
从内而外看,您对元组元素进行了重新排序: tuple< ; Ts ...,T>
,然后尝试将其反转,然后将结果放入 tuple
,然后尝试将其反转那个 ...是吗? :)
Looking at it from the inside out, you reorder the tuple elements: tuple<Ts..., T>
, then you try to reverse that, then you put the result in a tuple
, then you try to reverse that ... huh?! :)
这意味着每次实例化 tuple_reverse
时,都给它一个相同大小的元组,因此永远不会完成,并永久地递归实例化自身。 (然后,如果该递归甚至完成了,则将结果元组类型放入一个元组中,这样您就有一个包含N元元素元组的单元元素元组,并对其进行反转,这无济于事,因为反转单元元组是一个
This means each time you instantiate tuple_reverse
you give it a tuple of the same size, so it never finishes, and recursively instantiates itself forever. (Then, if that recursion even finished, you put the resulting tuple type into a tuple, so you have a single-element tuple containing an N-element tuple, and reverse that, which does nothing because reversing a single-element tuple is a no-op.)
您要剥离其中一个元素,然后反转其余元素,然后再次将其连接起来:
You want to peel off one of the elements, then reverse the rest, and concatenate it back again:
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>()));
您不需要将其包装在元组中并再次反转:)
And you don't need to wrap it in a tuple and reverse it again :)
您还应该处理空的元组大小写,所以整个事情是:
And you should also handle the empty tuple case, so the whole thing is:
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>()));
};
我会做不同的事情。
使用C ++ 14来获取类型
To get just the type, using 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>>
{ };
或者您可以编写一个函数来反转实际的元组对象,然后使用 decltype(reverse(t))
获取类型。要在C ++ 14中反转类似元组的对象:
Or you can write a function to reverse an actual tuple object, then use decltype(reverse(t))
to get the type. To reverse a tuple-like object 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>());
}
在C ++ 11中使用 < integer_seq.h>
并添加返回类型和使用 remove_reference
删除元组类型的引用(因为 tuple_size
和 tuple_element
不适用于元组引用):
In C++11 use <integer_seq.h>
and add return types and use remove_reference
to strip references from the tuple type (because tuple_size
and tuple_element
don't work with references to tuples):
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>());
}