简体   繁体   中英

Reversing a C++ tuple

I want to reverse the contents of a C++ tuple. I'm trying the following code suggested in this answer :

template<typename T, size_t... I>
auto
reverse_impl(T&& t, redi::index_sequence<I...>)
-> std::tuple<typename std::tuple_element<sizeof...(I) - 1 - I, T>::type...>
{
    return std::make_tuple(std::get<sizeof...(I) - 1 - I>(std::forward<T>(t));
}

template<typename T>
auto
reverse(T&& t)
-> std::tuple<typename std::tuple_element<N - 1 - I, T>::type...>
{
    return reverse_impl(std::forward<T>(t),
                        redi::make_index_sequence<std::tuple_size<T>::value>());
}

But I get these error messages from g++ 4.8.1:

foo.cc: In function ‘std::tuple<typename std::tuple_element<((sizeof (I ...) - 1) - I), T>::type ...> reverse_impl(T&&, redi::index_sequence<I ...>)’:
foo.cc:12:76: error: parameter packs not expanded with ‘...’:
   return std::make_tuple(std::get<sizeof...(I) - 1 - I>(std::forward<T>(t)));
                                                                            ^
foo.cc:12:76: note:         ‘I’
foo.cc: At global scope:
foo.cc:18:43: error: ‘N’ was not declared in this scope
 -> std::tuple<typename std::tuple_element<N - 1 - I, T>::type...>
                                           ^
foo.cc:18:51: error: ‘I’ was not declared in this scope
 -> std::tuple<typename std::tuple_element<N - 1 - I, T>::type...>
                                                   ^
foo.cc:18:55: error: template argument 1 is invalid
 -> std::tuple<typename std::tuple_element<N - 1 - I, T>::type...>
                                                       ^
foo.cc:18:62: error: expected parameter pack before ‘...’
 -> std::tuple<typename std::tuple_element<N - 1 - I, T>::type...>
                                                              ^
foo.cc:18:65: error: template argument 1 is invalid
 -> std::tuple<typename std::tuple_element<N - 1 - I, T>::type...>
                                                                 ^

And I have no idea how to fix it. Any ideas?

I don't think the code you posted matches the error message. To get that error there should be another ) after std::forward<T>(t) , but to fix that error it should be )...

The code is still bogus though, what is N in the second function? (This is apparently my fault, since the answer it was copied from was mine too!)

It should be:

template<typename T>
auto
reverse(T&& t)
-> decltype(reverse_impl(std::forward<T>(t),
                        redi::make_index_sequence<std::tuple_size<T>::value>()))

That still doesn't work, because when called with an lvalue tuple, the type T is deduced as std::tuple<...>& and you can't use tuple_size or tuple_element on references, so you need to remove the references:

#include <tuple>
#if __cplusplus > 201103L
namespace redi = std;
#else
#include <integer_seq.h>
#endif

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>());
}

int main()
{
  std::tuple<int, char, double> t;
  std::tuple<double, char, int> tt;
  tt = reverse(t);                  // test with lvalue
  tt = reverse(std::move(t));       // test with rvalue
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM