Я только что обновился до GCC 4.8, и некоторые переменные код шаблона больше не компилируется правильно. Я создал минимальный пример ниже:
#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;
}
Выводом этого будет (если комментируете неверную версию для GCC 4.6.3 / 4.8)
«А».
Ошибка, созданная GCC 4.6.3:
./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 ...>&)
Ошибка, созданная GCC 4.8:
./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 );
Кажется, что в GCC 4.8 переменные типы шаблонов меняются местами при раскрытии, хотя, как ни странно, они не «действительно» обращаются вспять, что подтверждается выводом — это будет «a» независимо от порядка. Clang 3.3 согласен с выходом GCC 4.6.3.
Это ошибка в GCC 4.8 или что-то еще?
РЕДАКТИРОВАТЬ: добавил отчет об ошибках в GCC здесь: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56774
Для меня это похоже на ошибку, похоже, что GCC 4.8.0 и GCC 4.7.2 затронуты. Clang 3.2 и GCC 4.6.3 соглашаются, что первый вызов something
является правильным, и я действительно не вижу, как GCC 4.7.2+ может считать второй вызов приемлемым.
Я бы сказал: сообщить об ошибке в GCC.
Обновить: Я добавил минималистичный пример в отчет об ошибках GCC, просто чтобы помочь им и доказать, что это чисто ошибка компилятора и не имеет ничего общего с std::tuple
, Вот сокращенный код:
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);
}
Обновление 2: Теперь это исправлено для GCC 4.7.3, GCC 4.8.1 и GCC 4.9 — благодарность команде GCC за безумно быстрое исправление!
Других решений пока нет …