0

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?

Community
  • 1
  • 1
Elektito
  • 3,863
  • 8
  • 42
  • 72

1 Answers1

5

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
}
Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
  • I fixed an obviously missing parenthesis but changed nothing else. This is from an accepted SO answer. I was wondering about N too. This is obviously wrong, but I've been trying to fix it for an hour or so. To no avail! – Elektito Aug 04 '14 at 13:00
  • 1
    Answer updated with working code, and I've fixed the linked answer – Jonathan Wakely Aug 04 '14 at 13:02