1

私は次の設定をしています:

template <typename T>
void foo(T& t);
void foo(const int& t);

void f()
{
    int i;
    foo(i); //Unresolved reference to "void foo<int>(int &)"
    foo(const_cast<const int&>(i)); //Unresolved reference to "void foo(int const &)"
}

fooの最初の呼び出しでは、非テンプレートの引数がiの型と一致しないため、コンパイラはテンプレートバージョンを呼び出そうとします。2番目の呼び出しでは、非テンプレートバージョンが呼び出されます。Microsoft C ++コンパイラバージョン10を使用しています。これは標準の動作ですか?型が完全に一致していない場合、const修飾子しかない場合でも、テンプレート関数が呼び出されますか?

編集:私はこれらの2つの関数に定義がないことを知っています。コンパイラーが何を呼び出したいかをより明確にするために、リンカーが何について不平を言っているかを指摘しているだけです。

4

3 に答える 3

4

はい、この動作はC++11標準に従って正しいです。

最初のケースでは、引数は非const整数への参照です。両方のオーバーロードはこの呼び出しを解決するために実行可能ですが、関数テンプレートは完全一致を許可しますが、非テンプレートオーバーロードは資格変換を必要とします。

2番目のケースでは、両方が完全に一致しますが、オーバーロードの1つは関数テンプレートではないため、関数テンプレートよりも優れた候補です。§13.3.3/1によると、実際には:

これらの定義を前提として、すべての引数iについて、ICSi(F1)がICSi(F2)よりも悪い変換シーケンスではない場合、実行可能な関数F1は別の実行可能な関数F2よりも優れた関数であると定義されます。

—一部の引数jの場合、ICSj(F1)はICSj(F2)よりも優れた変換シーケンスです。そうでない場合は、

—コンテキストは、ユーザー定義の変換(8.5、13.3.1.5、および13.3.1.6を参照)による初期化と、F1の戻りタイプから宛先タイプ(つまり、初期化されるエンティティのタイプ)への標準変換シーケンスです。 F2の戻りタイプから宛先タイプへの標準変換シーケンスよりも優れた変換シーケンスです。[...]または、そうでない場合は、

F1は非テンプレート関数であり、F2は関数テンプレートの特殊化です。そうでない場合は、

— [...]

于 2013-03-24T16:46:09.500 に答える
2

これは標準的な動作ですか?型が完全に一致していない場合、const修飾子しかない場合でも、テンプレート関数が呼び出されますか?

はい、それは規格によって明確に定義されています。

完全一致がない場合は、テンプレートが使用されます。これは、インスタンス化されたテンプレートバージョンが、変換が必要なバージョンよりint &も常に一致しているためです(変換へのint const&変換であっても)。

于 2013-03-24T16:44:11.807 に答える
-1

これはうまくいくはずです

#include <iostream>

template <typename T>
void foo(T& t) {}
void foo(const int& t){}

void f() 
{
    int i;
    foo(i); //Unresolved reference to "void foo<int>(int &)"
    foo(const_cast<const int&>(i)); //Unresolved reference to "void foo(int const &);
}

int main()
{
    f();
}
于 2013-03-24T16:43:41.643 に答える