2012-03-23 7 views
26

には、次のC++のプログラムを検討関数テンプレートdynamic_pointer_castでは動作しません理由:MSVC 2010でコンパイルする場合引数依存の照合が

#include <memory> 

struct A {}; 

struct B : A {}; 

int main() 
{ 
    auto x = std::make_shared<A>(); 
    if (auto p = dynamic_pointer_cast<B>(x)); 
} 

を、私は次のエラーを取得:

error C2065: 'dynamic_pointer_cast' : undeclared identifier 

エラーが解消されませんもしautostd::shared_ptr<A>に置き換えられれば。 std::dynamic_pointer_castで通話を完全に限定すると、プログラムは正常にコンパイルされます。

また、gcc 4.5.1はどちらかそれを好きではない:

error: 'dynamic_pointer_cast' was not declared in this scope 

私はstd::dynamic_pointer_caststd名前空間のx生活の種類以来、Koenig lookupによって選ばれていたであろうと思いました。私はここで何が欠けていますか?

+0

** std :: dynamic_pointer_cast **がスローアップするのは何ですか? – DumbCoder

+0

@DumbCoder:私が言ったように、プログラムは 'std :: dynamic_pointer_cast'を使うとコンパイルします。私は、なぜコンパイラがADLによって 'dynamic_pointer_cast'を選択しないのか不思議です。 –

+0

申し訳ありませんが、その部分をスキミング、私の悪い!! – DumbCoder

答えて

24

私はセクション§14.8.1/ 6(C++ 03、と私はそれがまた、C++ 11の中に保持していると思います)として読み込み、この場合に適用され、

[Note: For simple function names, argument dependent lookup (3.4.2) applies even when the function name is not visible within the scope of the call. This is because the call still has the syntactic form of a function call (3.4.1). But when a function template with explicit template arguments is used, the call does not have the correct syntactic form unless there is a function template with that name visible at the point of the call. If no such name is visible, the call is not syntactically well-formed and argument-dependent lookup does not apply. If some such name is visible, argument dependent lookup applies and additional function templates may be found in other namespaces.

[Example:

namespace A { 
    struct B { }; 
    template<int X> void f(B); 
} 
namespace C { 
    template<class T> void f(T t); 
} 
void g(A::B b) { 
    f<3>(b); //ill-formed: not a function call 
    A::f<3>(b); //well-formed 
    C::f<3>(b); //ill-formed; argument dependent lookup 
       // applies only to unqualified names 

    using C::f; 
    f<3>(b); //well-formed because C::f is visible; then 
       // A::f is found by argument dependent lookup 
} 

—end example] —end note]

あなたのケースではないんだと思いますあなたが明示的dynamic_pointer_castを呼び出すサイトで入手可能な同じ名前のテンプレートが存在しないテンプレート引数を渡すので、ADLを誘発します。 ADLを有効にする

1つのトリックは、以下に示すように、あなたのコードに同じ名前のダミーのテンプレートを追加することです:

#include <memory> 

struct A {}; 

struct B : A {}; 

template<int> //template parameter could be anything! 
void dynamic_pointer_cast(); //ADD this. NO NEED TO DEFINE IT 

int main() 
{ 
    auto x = std::make_shared<A>(); 
    if (auto p = dynamic_pointer_cast<B>(x)); //now it should work through ADL 
} 
+1

パーフェクト。私はこれがまだC++ 11のために成立していると推測できます。ありがとう! –

+0

@AlexandreC .:私はC++ 11でもそうだと思います。 – Nawaz

+1

ああ!ニースのトリックも。 –

18

ケーニッヒルックアップは機能だけを見つけるに適用されます。ここでは、まずテンプレートを見つけてからインスタンス化しなければなりません。単純にコードを解析するために、コンパイラはdynamic_pointer_castがテンプレートであることを知っていなければなりません(そうでなければ '<'はテンプレート引数リストの先頭ではありません)。コンパイラがdynamic_pointer_castが関数テンプレートであることを知るまでは、関数呼び出しが関与していることさえ知りません。表示される表現は基本的にa <b> cです。<>は関係演算子です。

+0

Koenigルックアップも関数テンプレートを見つけることができます。ナワズの答え。それにもかかわらず、あなたの議論は正しいものです。 –

+0

Pedenicallyに言えば、Koenigルックアップは関数テンプレートにも適用されます。明示的にテンプレートの引数を渡しても、テンプレートの名前が呼び出しのサイトに表示されないときには機能しません。この場合、コンパイラは名前が実際に関数テンプレートの名前であることを知らないため、コールに正しい関数呼び出し構文がないため、この関数は機能しません。 – Nawaz

+5

@ Nawaz最後に、標準ではそうではないと言われているため、標準では機能しないと言っている理由はいくつかあります。あなたが与えるものと説明したもの(委員会での議論から来ています)は同じ基本問題に戻ります。式を正しく解析するためには、コンパイラはシンボルがそれを知るためには、それを調べなければなりません。関数呼び出しがあることを知るのに十分な解析をまだ行っていないため、Koenigルックアップを使用して検索することはできません。 –

関連する問題