23

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 の間違ったバージョンをコメントアウトした場合) 'a' になります。

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

4

1 に答える 1

15

これは私にはバグのように見えます。GCC 4.8.0 と GCC 4.7.2 が影響を受けているようです。Clang 3.2 と GCC 4.6.3 は、への最初の呼び出しsomethingが正しいことに同意しており、GCC 4.7.2+ が 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 チームに感謝します。

于 2013-03-28T21:11:54.597 に答える