2012-03-23 18 views
26

考慮下面的C++程序中工作:爲什麼參數依賴查找不符合函數模板dynamic_pointer_cast

#include <memory> 

struct A {}; 

struct B : A {}; 

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

當2010 MSVC編譯,我得到以下錯誤:

error C2065: 'dynamic_pointer_cast' : undeclared identifier 

的錯誤仍然存​​在如果auto被替換爲std::shared_ptr<A>。當我完全符合std::dynamic_pointer_cast的要求時,程序成功編譯。

此外,gcc 4.5.1不喜歡,要麼:

error: 'dynamic_pointer_cast' was not declared in this scope 

我認爲std::dynamic_pointer_cast會被Koenig lookup採摘,因爲x生活在std命名空間中的類型。我在這裏錯過了什麼?

+0

是什麼讓它** std :: dynamic_pointer_cast **拋出? – DumbCoder 2012-03-23 12:06:02

+0

@DumbCoder:就像我說的,程序在我使用'std :: dynamic_pointer_cast'時編譯。我只是好奇編譯器爲什麼不選擇ADL的'dynamic_pointer_cast'。 – 2012-03-23 12:06:47

+0

不好意思剔除那部分,我的壞! – DumbCoder 2012-03-23 12:08:28

回答

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]

你的情況不觸發ADL,因爲您顯式傳遞模板參數,因此在調用dynamic_pointer_cast的站點上沒有可用的同名模板。

一招,使ADL是與相同名稱添加一個虛擬模板代碼,如下圖所示:

#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。謝謝! – 2012-03-23 12:10:04

+0

@AlexandreC .:我認爲它也適用於C++ 11。 – Nawaz 2012-03-23 12:14:06

+1

啊哈!好戲也是。 – 2012-03-23 12:17:07

18

Koenig查找只適用於發現功能。在這裏,你必須首先找到一個模板,然後在你有一個函數之前實例化它。爲了簡單地解析代碼,編譯器必須知道dynamic_pointer_cast是一個模板(否則,'<'小於,而不是模板參數列表的開始);直到編譯器知道dynamic_pointer_cast是一個函數模板,它甚至不知道涉及函數調用。它看到的表達基本上是a <b> c,其中<>是關係運算符。

+0

似乎Koenig查找也可以找到函數模板,參見。納瓦茲的回答。儘管如此,你的論點是正確的。 – 2012-03-23 12:11:46

+0

迂迴地說,Koenig查找也適用於函數模板。當你明確地傳遞模板參數並且模板名稱在調用的站點上不可見時,它不起作用。在這種情況下,它不起作用,因爲調用沒有正確的函數調用語法,因爲編譯器不知道該名稱實際上是函數模板的名稱。 – Nawaz 2012-03-23 12:23:46

+5

@Nawaz最終,它不起作用,因爲該標準沒有這樣做,並且標準沒有說使其起作用的原因有幾個。無論是你給的還是我所解釋的(來自委員會的討論,很多年前)都回到了同樣的基本問題:爲了正確解析表達式,編譯器必須知道符號是模板,並且爲了知道它,它必須查找它。它不能使用Koenig查找查找它,因爲它還沒有足夠的分析知道有一個函數調用。 – 2012-03-23 13:54:35

相關問題