4

C++ では、関数と同じ名前空間で宣言された型のオブジェクトを最初の引数として受け取る関数を使用する場合、名前空間の修飾を省略できます。ただし、これはテンプレート化された関数 ( std::getなど) では機能しないことに気付きました。これが実際にテンプレートに関連していることを確認するために、簡単な例を書きました。

namespace ns {

    struct S {};

    void sFoo(const S&) {}
    template<typename T> void sBar(const S&) {}
}

void foo()
{
    ns::S s;
    sFoo(s); // ok
    sBar<int>(s); // error: ‘sBar’ was not declared in this scope
    ns::sBar<int>(s); // ok
}

明示的なインスタンス化を試みましたが、何も変更されませんでした (変更されたとしても、単に using を使用するよりも悪いオプションになります)

では、名前空間を指定せずにテンプレート化された関数を正確に呼び出すことができないのはなぜですか (そして、名前空間ディレクティブを使用も使用もしていないと仮定します)?

4

1 に答える 1

2

sBarは関数ではなく、関数テンプレートです。引数依存のルックアップは、関数名に対してのみ機能します。確かにsBar<int>関数ですが、適切な名前がわからないとテンプレートをインスタンス化できません!

これとは関係なく、テンプレートの引数が推測できる場合、その ADL は機能します。

namespace ns
{
    template <typename T> void sZip(T &) { }
}

void foo()
{
    ns::S s;
    sZip(s);  // OK, deduces T = ns::S
}

C++ の一般的な "ベスト プラクティス" は、引数が推定できる場合にのみ関数テンプレートを作成し、引数を明示的に指定しないことです。(この規則の例外は、目的の結果の型に対して 1 つの必須引数を必要std::forwardとするさまざまな関数です。)make_*

于 2012-11-12T18:21:54.627 に答える