2012-03-23 20 views
26

पर विचार करें निम्नलिखित सी ++ प्रोग्राम समारोह टेम्पलेट के साथ काम नहीं करता है:क्यों तर्क आश्रित लुक 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)); 
} 

जब MSVC 2010 संकलन, मैं निम्न त्रुटि प्राप्त:

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_cast हैं std नाम स्थान में x जीवन के प्रकार के बाद से, Koenig lookup द्वारा उठाया गया है। मुझे यहां क्या समझ नहीं आ रहा है ?

+0

इसे क्या बना रहा है ** std :: dynamic_pointer_cast ** फेंकता है? – DumbCoder

+0

@DumbCoder: जैसा कि मैंने कहा था, जब मैं 'std :: dynamic_pointer_cast' का उपयोग करता हूं तो प्रोग्राम संकलित करता है। मैं इस बारे में उत्सुक हूं कि क्यों कंपेलर एडीएल द्वारा 'dynamic_pointer_cast' नहीं चुनता है। –

+0

क्षमा करें उस भाग को स्किम किया, मेरा बुरा !! – DumbCoder

उत्तर

24

मुझे लगता है कि खंड §14.8.1/6 (सी ++ 03, और मुझे लगता है कि उस में रखती है सी ++ 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 है सक्षम करने के लिए जिन्हें आप नीचे अपने कोड के साथ ही नाम एक डमी टेम्पलेट जोड़ने के लिए,:

#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

बिल्कुल सही। मुझे लगता है कि हम यह मान सकते हैं कि यह अभी भी सी ++ 11 के लिए है। धन्यवाद! –

+0

@AlexandreC .: मुझे लगता है कि यह सी ++ 11 में भी है। – Nawaz

+1

आह! अच्छी चाल भी। –

18

कोएनिग देखने केवल कार्यों पाने के लिए लागू होता है। यहां, आपको पहले फ़ंक्शन ढूंढने से पहले टेम्पलेट ढूंढना होगा, फिर इसे तुरंत चालू करना होगा। कोड को बस पार्स करने के लिए, कंपाइलर को यह जानना होगा कि dynamic_pointer_cast एक टेम्पलेट है (अन्यथा, '<' टेम्पलेट तर्क सूची की शुरुआत से कम नहीं है); जब तक संकलक जानता है कि dynamic_pointer_cast एक फ़ंक्शन टेम्पलेट है, यह यह भी नहीं जानता कि फ़ंक्शन कॉल शामिल है। यह अभिव्यक्ति मूल रूप से a <b> c है, जहां < और > संबंधपरक ऑपरेटर हैं।

+0

ऐसा लगता है कि कोएनिग लुकअप फ़ंक्शन टेम्पलेट्स भी ढूंढ सकता है, सीएफ। नवाज का जवाब फिर भी, आपका तर्क सही है। –

+0

पैडेंटिकली बोलते हुए, कोएनिग लुकअप फ़ंक्शन टेम्पलेट पर भी लागू होता है। जब आप स्पष्ट रूप से टेम्पलेट तर्क पास करते हैं तो यह काम नहीं करता है और कॉल के स्थान पर टेम्पलेट का नाम दिखाई नहीं देता है। इस मामले में, यह काम नहीं करता है क्योंकि कॉल में सही फ़ंक्शन-कॉल सिंटैक्स नहीं है, क्योंकि संकलक यह नहीं जानता कि नाम वास्तव में फ़ंक्शन टेम्पलेट का नाम है। – Nawaz

+5

@ नवाज अंत में, यह काम नहीं करता है क्योंकि मानक कहता है कि यह नहीं करता है, और कई कारण हैं कि मानक यह नहीं कहता कि यह काम क्यों करता है।आप जो भी देते हैं और जो मैंने समझाया है (जो समिति में चर्चाओं से आता है, कई साल पहले) एक ही मूल समस्या पर वापस आ जाता है: अभिव्यक्ति को सही तरीके से पार्स करने के लिए, संकलक को यह जानना है कि प्रतीक एक है टेम्पलेट, और यह जानने के लिए, इसे देखना है। और यह इसे देखने के लिए कोएनिग लुकअप का उपयोग नहीं कर सकता है, क्योंकि अभी तक यह पता लगाने के लिए पर्याप्त रूप से विश्लेषण नहीं किया गया है कि एक फ़ंक्शन कॉल है। –