2

VS2010 で次のコードを実行しました。

#include <iostream>

template<class T> // (a) a base template 
void f( T )
{    std::cout << "(a)" << std::endll;}

template<class T> // (b) a second base template, overloads (a) 
void f( T* )     //     (function templates can't be partially 
{    std::cout << "(b)" << std::endll;}

template<>        // (c) explicit specialization of (b) 
void f<>(int*)
{    std::cout << "(c)" << std::endll;}

int main(int argc, char* argv[])
{
    int *p = new int(10); 
    f( p ); // '(c)'

    return 0;
}

/////////////////

#include <iostream>

template<class T> // (a) same old base template as before 
void f( T )
{    std::cout << "(a)" << std::endll;}

template<>        // (c) explicit specialization, this time of (a)
void f<>(int*)
{    std::cout << "(c)" << std::endll;}

template<class T> // (b) a second base template, overloads (a) 
void f( T* )
{    std::cout << "(b)" << std::endll;}

int main(int argc, char* argv[])
{
    int *p = new int(10); 
    f( p ); // '(b)'

    return 0;
}

出力結果は(c)です。ただし、(c) コードのブロックを (b) の前に移動すると、出力結果は になり(b)ます。関連記事http://www.gotw.ca/publications/mill17.htmを読みました。それでも混乱する。

この場合、コードの順序が重要なのはなぜですか?

4

2 に答える 2

2

質問のほとんどの情報はすでにお持ちだと思います。問題は、オーバーロードであり、関連のない 2 つの基本テンプレートがあることです。

最初のテンプレートのみが宣言されているときに特殊化が実行されると、コンパイラはそれを の最初のテンプレートの特殊化と見なしT == int*ます。両方のテンプレートが宣言された後、呼び出しを実行すると、コンパイラは基本テンプレートのみを調べて、2 番目のテンプレートの方が式により適していると判断します。2 番目のテンプレートには特殊化がないため、基本テンプレート定義が使用されます。

テンプレートの特殊化は、基本テンプレートが選択された後にのみ機能します。コンパイラが選択する基本テンプレートには影響しません。

2 番目のテンプレートが宣言された後に特殊化を に移動すると、コンパイラはその特殊化を 2 番目の基本テンプレートと一致させT == intます。この場合、コンパイラがその 2 番目のテンプレートを呼び出しに最適なものとして選択するとmain、特殊化が開始され、特殊化された動作が得られます。

于 2012-08-16T15:07:51.243 に答える
1

記事でも解説しているように、特化を移すとどの機能が特化されるかが変わります。(b) の前に特殊化を置くと、(a) を特殊化します。

template<>        // (c) explicit specialization of (a) <-- here
void f<>(int*)
{    cout << "(c)" << endl;}

どちらの場合も、 を呼び出すf(p)と、コンパイラは最初に (a) と (b) を調べて、どちらのオーバーロードが適しているかを判断します。リストした記事で説明されているように、専門化はオーバーロードの解決に参加しないため、両方の例で (b) を選択します。その時点で、(b) の特殊化を探します。

最初のケースでは、(b) を (c) で特殊化したので、(c) を実行します。2 番目のケースでは、(b) を特化していないため、(b) を実行します。

編集: 順序が問題にならないようにする最も簡単な方法は、特殊化を提供する前に (a) と (b) の両方を前方宣言することです。その場合、コンパイラは意図したものを推測できます。http://ideone.com/qj2JCを参照

于 2012-08-16T15:09:22.177 に答える