如何反转元组? [英] How do I reverse a tuple?
问题描述
如何逆转元组中的类型?例如,我要 reverse_tuple< std :: tuple< int,char,bool>> :: type
为 std :: tuple< bool ,char,int>
。我试着做以下,但它没有工作。我做错了什么?
#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()
{
使用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& >'
prog.cpp:15:34:需要从'struct tuple_reverse< std :: tuple< int,bool,char> >'
prog.cpp:29:31:此处需要
prog.cpp:15:34:error:没有在'struct tuple_reverse< std :: tuple< int,bool,char> >'
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
... huh ?! :)
这意味着每次你实例化 tuple_reverse
,你给它一个大小相同的元组,完成,并递归地实例化自己永远。 (然后,如果递归甚至完成,你把结果的元组类型放入一个元组,所以你有一个单元素元组包含一个N元素元组,反过来,这不做什么,因为反转单元素元组是一个无操作。)
您要剥离其中一个元素,然后反转其余元素,然后重新连接:
using head = std :: tuple< T>
using tail = typename tuple_reverse< std :: tuple< Ts ...>> :: type;
使用type = decltype(std :: tuple_cat(std :: declval< tail>(),std :: declval< head>()));
而且你不需要将它换成一个元组, >
您还应该处理空元组的情况,所以整个事情是:
template< typename ... Ts>
struct tuple_reverse;
模板<>
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;
使用type = decltype(std :: tuple_cat(std :: declval< tail>(),std :: declval< head>()
};
我会做不同的。
要获得类型,使用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 ...>类型;
};
//用于处理空元组的部分专门化:
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中反转一个类似tuple的对象:
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& :: tuple_size< T> :: value>());
}
在C ++ 11中使用 < integer_seq.h>
并添加返回类型和使用 remove_reference
以从元组类型剥离引用(因为 tuple_size
和 tuple_element
不使用对元组的引用):
模板< 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))...)
}
模板< 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>());
}
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, ""
);
}
Here are my errors:
prog.cpp: In instantiation of ‘struct tuple_reverse<std::tuple<char, int, bool> >’:
prog.cpp:15:34: recursively required from ‘struct tuple_reverse<std::tuple<bool, char, int> >’
prog.cpp:15:34: required from ‘struct tuple_reverse<std::tuple<int, bool, char> >’
prog.cpp:29:31: required from here
prog.cpp:15:34: error: no type named ‘type’ in ‘struct tuple_reverse<std::tuple<int, bool, char> >’
prog.cpp: In function ‘int main()’:
prog.cpp:30:9: error: template argument 1 is invalid
Any answers are appreciated. Thanks.
What you did wrong was here:
using type = typename tuple_reverse<
std::tuple<
typename tuple_reverse<std::tuple<Ts..., T>>::type
>
>::type;
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?! :)
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>()));
};
I'd do it differently though.
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>>
{ };
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>());
}
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>());
}
这篇关于如何反转元组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!