2

「C++テンプレート-完全ガイド」という本のセクション2.4 Overloading Function Templatesには、次の例があります。

// maximum of two int values
inline int const& max (int const& a, int const& b)
{
    return a < b ? b : a;
}
// maximum of two values of any type
template <typename T>
inline T const& max (T const& a, T const& b)
{
    return a < b ? b : a;
}
// maximum of three values of any type
template <typename T>
inline T const& max (T const& a, T const& b, T const& c)
{
    return max (max(a,b), c);
}
int main()
{
    ::max(7, 42); // calls the nontemplate for two ints (1)
}

ただし、付録BのB.2簡略化された過負荷解決では、著者は次のように述べています。

過負荷の解決は、テンプレートの引数の推定後に発生することに注意してください...(2)

によると(2)、引数の演繹によって::max(7,42)呼び出す必要があります。max<int>

4

4 に答える 4

4

cv関数が修飾子を含めて両方とも完全に一致する場合、コンパイラはオーバーロード解決で非テンプレート関数を優先します。

したがって、テンプレート化された関数は基本的に同じになりますが、ここでは非テンプレートが選択されます。

編集:

標準ドラフトN3485で私はこれを見つけました:

13.3.3最高の実行可能な関数[over.match.best]

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

..。

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

— F1とF2は関数テンプレートの特殊化であり、F1の関数テンプレートは、14.5.6.2で説明されている半順序規則に従って、F2のテンプレートよりも特殊化されています。

..。

于 2013-03-04T18:21:01.717 に答える
3

によると(2)、引数の演繹によって::max(7,42)呼び出す必要があります。max<int>

いいえ。考えてみてください。オーバーロードの解決を行うには(つまり、最適なものを選択するために)、コンパイラーは最初に使用可能なすべてのオーバーロードを認識し、それらを比較できる必要があります。関数テンプレート自体は有効な関数ではないことに注意してください。実際の関数を作成するには、最初に関数テンプレートをインスタンス化する必要があります。

これは、最初に、コンパイラがという名前のすべての関数テンプレートmaxを処理し、それらすべてに対してテンプレート引数の推定を試みてから、非テンプレート関数とともにインスタンス化された関数のオーバーロード解決を実行することを意味します。

関数の視覚化は次のとおりです(簡潔にするためにcv-qualifiersを省略しています)。

                    int max(int, int);
template<class Arg> Arg max(Arg, Arg);
template<class Arg> Arg max(Arg, Arg, Arg);

呼び出しを見ていきましょう::max(7, 42)

まず、コンパイラーは3つの候補関数があることを確認します。ただし、の最初の過負荷をmax他の2つと比較することはできません。これは、リンゴとオレンジを比較するようなものです。代わりに、最初に関数テンプレートのブループリントから実際の関数を「スタンプアウト」する必要があります。これは、私たちの場合、テンプレート引数の推論によって発生します。

int max(int, int); // originally non-template
int max(int, int); // originally template
int max(int, int, int); // not enough arguments, invalid

引数/パラメーターの数が一致しないために3番目のオーバーロードがスローされるため、2つになります。過負荷の解決の観点からは、どちらも同じですが、待ってください。ここで、特定のルールのステップが次のようになります。

§13.3.3 [over.match.best] p1

[...]これらの定義を前提として、実行可能な関数F1は、次の場合に別の実行可能な関数よりも優れた関数であると定義されますF2[...]:

  • F1非テンプレート関数でF2あり、関数テンプレートの特殊化であり、
于 2013-03-04T18:36:48.087 に答える
2

テンプレート引数推定のオーバーロード解決後、

1) inline int const& max (int const& a, int const& b);

2) template <>
   inline int const& max (int const& a, int const& b)

この状況では、1) は C++ 標準 13.3.3 par で指定されているように呼び出されます。1 (ドラフトn3092 )。

msdn も明確に述べています。

非テンプレート関数がテンプレート関数と同等に一致する場合、非テンプレート関数が選択されます

http://msdn.microsoft.com/en-us/library/s016dfe8%28v=vs.80%29.aspx

于 2013-03-04T18:23:56.547 に答える
1

C++11 標準のパラグラフ 13.3.3/1 (オーバーロード解決のコンテキストでの「実行可能な最適な関数」) によると:

ICSi(F) を次のように定義します。

— F が静的メンバー関数である場合、ICS1 (F) は、任意の関数 G について ICS1 (F) が ICS1 (G) より良くも悪くもなく、対称的に、ICS1 (G) がより良くも悪くもないように定義されます。 ICS1 (F)132; それ以外は、

— ICSi(F) は、リスト内の i 番目の引数を実行可能な関数 F の i 番目のパラメーターの型に変換する暗黙の変換シーケンスを示します。 1 つの暗黙的な変換シーケンスが、別の変換シーケンスよりも優れた変換シーケンスまたは悪い変換シーケンスになることを意味します。

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

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

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

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

— F1 と F2 は関数テンプレートの特殊化であり、F1 の関数テンプレートは、14.5.6.2 で説明されている半順序規則に従って、F2 のテンプレートよりも特殊化されています。

これは、オーバーロード解決のコンテキストでは、関数テンプレートをインスタンス化することによって生成された関数 (したがって、型推定後) が非テンプレート関数と同等に一致する場合、非テンプレート関数が優先されることを意味します。

于 2013-03-04T18:35:07.173 に答える