6

ここでは一例です:私はこのプログラムをコンパイルしようとしたとき引数依存の検索および関数テンプレート

#include <string> 
#include <algorithm> 
#include <memory> 

using std::string; 

int main() 
{ 
    string str = "This is a string"; 

    // ok: needn't using declaration, ADL works 
    auto it = find(str.begin(), str.end(), 'i'); 

    // error: why ADL doesn't work? 
    std::shared_ptr<string> sp = make_shared<string>(str); 
} 

は、コンパイラが訴え:

error: no template named 'make_shared'; did you mean 'std::make_shared'? 
     std::shared_ptr<string> sp = make_shared<string>(str); // error... 
            ^~~~~~~~~~~ 
            std::make_shared 

私は最初の関数findにはないと思います引数に依存する検索(ADL)のため、using宣言が必要です。コンパイラは、stringが存在するネームスペース(つまり、std)を検索し、find。しかし、2番目の関数make_sharedでは、ADLが機能しないようです。代わりにstd::make_sharedまたはusing宣言を使用する必要があります。私は2つの関数テンプレートの定義が異なっている知っている:前者は関数のパラメータ型としてそのテンプレート偶然にの1(typename Tまたはそのような何かを)取り、同じ型を返します。後者は、関数パラメータパックを関数パラメータとして取り込み、その戻り値の型は別のテンプレートパラメータです。この違いはADLを無効にしますか?あるいは、その質問に答えるのを手伝って、参考文献を提供することができますか?

+1

最初の使用法は脆弱です。イテレータの型が 'std'に存在するという不特定の状況に頼っています。別の日にイテレータの型が 'const char *'ならば、それはコンパイルされません。 –

+0

私はそれが 'using'宣言を省略することは脆い方法であることを知っています。 2番目のものと比較して> _ <||| – chihyang

+0

@chihyang:良い例は 'begin(str)'でしょう。 – Jarod42

答えて

1

引数依存ルックアップは、未修飾の関数呼び出し式で機能します。これは、関数テンプレートの特殊化だけでなく、「通常の」関数にも当てはまります。

foo<3>(x) // "foo less than three?" 

な場合は、ADLを誘発しない理由です:あなたはテンプレート関数の明示的なテンプレートパラメータを提供する際

しかし、その後、式が構文的に関数呼び出しのようには見えません。しかし、一旦名前がと知られていれば、がテンプレートになると、ADLが適用されます!

template <int> void foo(); 

foo<double, 5, T>(x); // uses ADL 
+0

[デモ](https://ideone.com/SKc0Sh) –

+0

まあ...私はあなたの答えに道を試み、それはうまくいった!しかし、本当に不思議な感じです。私たちが使用している名前がテンプレートであることをコンパイラに通知するために使用することのない別の関数テンプレートを宣言してください!なぜADLは変だ? C++ Primerでは3ページ以下です。しかし、今は巨大な落とし穴のように見える! – chihyang

+0

@chihyang:そうです。しかし、現実のアプリケーションではこれが大したことではないことが時々考えられます。 @CHHYAN; –

0

テンプレートメソッドでは、明示的にテンプレートの引数を<>と指定しても、スコープ内に(同じ名前の)表示可能なテンプレートメソッドがある場合を除き、ADLは使用されません。

+0

まず、明示的に指定されたテンプレートパラメータを持つ関数呼び出しにのみ適用されます。第2に、スコープ内に別の関数テンプレートもある場合は、ADLが適用されます。この制限は本質的に深遠ではなく構文的です。既存の宣言がなければ、呼び出し式は構文的には関数呼び出しのようには見えません。 –

+0

@KerrekSB:確かに。言い直された – Jarod42

関連する問題