如何反转元组? [英] How do I reverse a tuple?

查看:140
本文介绍了如何反转元组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何逆转元组中的类型?例如,我要 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆