Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GCC 4.8 is reversing variadic template parameter pack

I just upgraded to GCC 4.8 and some variadic template code no longer compiles correctly. I've created a minimal example below:

#include <tuple>
#include <iostream>

template <class T, class ... OtherT>
void something( std::tuple<T, OtherT...> & tup )
{
  std::cout << std::get<1>(tup) << std::endl;
}

int main()
{
  std::tuple<int, char, bool> myTuple(3, 'a', true);

  // Compiles OK in GCC 4.6.3 but NOT 4.8
  something<int, char, bool>( myTuple );

  // Compiles OK in GCC 4.8 but NOT 4.6.3
  something<int, bool, char>( myTuple );

  return 0;
}

The output of this will be (if commenting out the incorrect version for GCC 4.6.3/4.8) 'a'.

The error produced by GCC 4.6.3 is:

./test.cpp: In function ‘int main()’:
./test.cpp:18:39: error: no matching function for call to ‘something(std::tuple<int, char, bool>&)’
./test.cpp:18:39: note: candidate is:
./test.cpp:5:6: note: template<class T, class ... OtherT> void something(std::tuple<_Head, _Tail ...>&)

The error produced by GCC 4.8 is:

./test.cpp: In function ‘int main()’:
./test.cpp:15:39: error: no matching function for call to ‘something(std::tuple<int, char, bool>&)’
   something<int, char, bool>( myTuple );
                                       ^
./test.cpp:15:39: note: candidate is:
./test.cpp:5:6: note: template<class T, class ... OtherT> void something(std::tuple<_El0, _El ...>&)
 void something( std::tuple<T, OtherT...> & tup )
      ^
./test.cpp:5:6: note:   template argument deduction/substitution failed:
./test.cpp:15:39: note:   mismatched types ‘bool’ and ‘char’
   something<int, char, bool>( myTuple );

It seems like in GCC 4.8, variadic template types are reversed when expanded, though oddly enough they don't "really" get reversed as proved by the output - it will be 'a' regardless of the ordering. Clang 3.3 agrees with the GCC 4.6.3 output.

Is this a bug in GCC 4.8 or something else?

EDIT: added a bug report to GCC here: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56774

like image 832
Azoth Avatar asked Mar 28 '13 21:03

Azoth


1 Answers

This looks like a bug to me, GCC 4.8.0 and GCC 4.7.2 seem to be affected. Clang 3.2 and GCC 4.6.3 agree that the first call to something is the correct one and I really fail to see how GCC 4.7.2+ can consider the second call to be acceptable.

I'd say: Report a bug against GCC.


Update: I added a minimalistic example to the GCC bug report, just to help them and prove that it's a pure compiler bug and has nothing to do with std::tuple. Here's the reduced code:

template< typename... > struct X {};

template< typename T, typename... Ts >
void f( X< T, Ts... >& ) {}

int main()
{
    X< int, bool, char > t;
    f< int, char, bool >(t);
}

Update 2: It's now fixed for GCC 4.7.3, GCC 4.8.1 and GCC 4.9 - kudos to the GCC team for an insanely fast fix!

like image 154
Daniel Frey Avatar answered Oct 18 '22 11:10

Daniel Frey