21

テンプレートの呼び出しでclangとコンパイルがスタックしたプロジェクト(gcc/g ++を使用しても問題ありません)をコンパイルしようとしています。同じエラー メッセージを表示する最も単純な同様のコードを作成しようとしました。ここにあります:

#include <vector>
#include <utility>
#include <iostream>

using namespace std;

int A( double in )
{
  return 1;
}

int A( int in )
{
  return 1;
}


template<class M, class T>
M test(T input, M (fun) (T) )
{
  return fun( input );
}



int main( int argc, const char *argv[] )
{
  cout << test( (int) 1, A ) << test( (double) 1.2, A ) << endl;
  return 0;
}

clang からのエラー (もちろん 2 回表示されます):

error: no matching function for call to 'test'
candidate template ignored: couldn't infer template argument 'M'

Gcc は文句を言いません。M は戻り型であり、常に「int」であることに注意してください。

誰かがどちらが正しいか、そしてその理由を知っていますか?

ありがとう

4

2 に答える 2

8

g++ は間違っています。C++11 [temp.deduct.type]p5 から:

[...] - 関連付けられた関数引数が [...] オーバーロードされた関数のセットであり、[...] 複数の関数であるため、引数推定を実行できない関数パラメーター関数パラメーターの型に一致します

この決定は、他の場所で推定された可能性のあるテンプレート パラメーターに関係なく行われるため、T推定する必要があるという事実intはここでは関係ありません。これにより、パラメーター全体がM (fun)(T)推定されないコンテキストになります。したがってM、Clang が主張するように、推測することはできません。

g++は、2 番目のパラメーターが推定されないコンテキストであるかどうかを判断するときに、最初の関数パラメーターからの' T= ' 推定を誤って使用しているようです。int関数パラメーターの順序を逆にすると、g++ もコードを拒否します。

int A(double);
int A(int);
template<class M, class T>
M test(M (fun) (T), T input) {
  return fun( input );
}
int main( int argc, const char *argv[]) {
  test(A, 1);
  test(A, 1.2); 
}
于 2013-07-30T00:41:47.787 に答える
2

私の以前の回答(現在は削除されています)は間違っていました。Clangは間違っています。

M関数の引数が であるため、コンパイラは型を推測できるはずですM(fun)(T)。関数ポインタの引数リストには no がないことに注意してくださいM。したがって、これは 14.8.2.5のT()(C++11) / (C++93) に対応します。T(*)()

where(T)は、少なくとも 1 つのパラメータ タイプに が含まれるパラメータ タイプリストT()表し、パラメータ タイプに が含まれないパラメータ タイプリストTを表します。

于 2013-07-23T11:25:32.003 に答える