2017-05-03 10 views
8

मेरे पास एक समस्या है जो this एक के समान है।सशर्त नोएसेप्ट और अधिभार के साथ असंगतता

संक्षेप में, मेरे पास magic विधि है, जो noexcept है यदि कोई अन्य विधि noexcept है।

अजीब बात यह है कि इस "एक और तरीका" दो भार के है, और संकलक दूसराmagicnoexcept -नेस निर्धारित करने के लिए अधिभार चुनता है।

हालांकि, जब magic पर बाद में कहा जाता है, पहले अधिभार कहा जाता है, लेकिन magic की noexcept -नेस ही रहता है!

यहाँ मैं क्या समझ से wandbox link

है:

  1. noexcept(magic(dummy2{})) कॉल
  2. noexcept(noexcept(adl_caller(...)) जो वापस
  3. adl_caller(..., priority_tag<0>) noexcept पर गिर जाता है user_method(dummy2) के बाद से इस बिंदु पर संकलक द्वारा ज्ञात नहीं है।

पर्याप्त मेला, हालांकि, user_method(dummy2) को ऊपर 3 पंक्तियों को कैसे कहा जाता है? क्या यह मानक द्वारा लक्षित है?

क्षमा करें अगर मैं पर्याप्त स्पष्ट नहीं हूं।

#include <iostream> 

template <unsigned N> struct priority_tag : priority_tag<N - 1> {}; 
template <> struct priority_tag<0> {}; 

template <typename T> 
auto adl_caller(T t, priority_tag<1>) noexcept(noexcept(user_method(t))) 
    -> decltype(user_method(t)) { 
    std::cout << "first adl_caller overload" << std::endl; 
    user_method(t); 
} 

// tricky noexcept ... 
template <typename T> void adl_caller(T, priority_tag<0>) noexcept { 
    std::cout << "second adl_caller overload" << std::endl; 
} 

template <typename T> 
void magic(T t) noexcept(noexcept(adl_caller(t, priority_tag<1>{}))) { 
    adl_caller(t, priority_tag<1>{}); 
} 

struct dummy {}; 
struct dummy2 {}; 

// un-commenting this line makes the above call to cout print '0' 
// void user_method(dummy2); 

void user_method(dummy) 
{ 
    // user_method(dummy2) is declared after this point 
    // this line prints '1', since magic falls back to the second adl_caller overload 
    std::cout << "noexcept?: " << noexcept(magic(dummy2{})) << std::endl; 
    std::cout << "dummy method called" << std::endl; 
    // however, the first adl_caller overload is called here ... 
    magic(dummy2{}); 
} 

void user_method(dummy2) 
{ 
    std::cout << "dummy2 method called" << std::endl; 
} 

int main() 
{ 
    magic(dummy{}); 
} 

उत्तर

6

[temp.point]/8:

एक समारोह टेम्पलेट के लिए एक विशेषज्ञता [...] हो सकता है एक अनुवाद इकाई के भीतर instantiations के कई अंक है, और इन्स्टेन्शियशन के अंक ऊपर वर्णित के अलावा , ऐसी विशेषज्ञता के लिए अनुवाद इकाई के भीतर तत्कालता का एक बिंदु है, अनुवाद इकाई के अंत को तत्कालता बिंदु भी माना जाता है। [...] अगर तत्काल के दो अलग-अलग बिंदु एक-परिभाषा नियम के अनुसार एक टेम्पलेट विशेषज्ञता को अलग-अलग अर्थ देते हैं, तो प्रोग्राम खराब हो गया है, कोई डायग्नोस्टिक आवश्यक नहीं है।

[temp.dep.candidate] की तुलना करें:

एक समारोह कॉल जहां पोस्टफ़िक्स अभिव्यक्ति एक आश्रित नाम है के लिए, उम्मीदवार कार्यों में हमेशा की तरह देखने नियम का उपयोग कर पाए जाते हैं ([basic.lookup.unqual ], [basic.lookup.argdep] कि को छोड़कर):

  • अयोग्य नाम देखने का उपयोग कर देखने के भाग के लिए, केवल मज़ा टेम्पलेट परिभाषा संदर्भ से ction घोषणाएं मिलती हैं।

  • देखने संबद्ध नामस्थान का उपयोग कर के भाग के लिए ([basic.lookup.argdep]), केवल समारोह घोषणाओं या तो टेम्पलेट परिभाषा संदर्भ या टेम्पलेट इन्स्टेन्शियशन संदर्भ में पाया पाए जाते हैं।

कॉल बीमार का गठन किया जाएगा, तो या एक बेहतर मैच में उन नामस्थान में शुरू की बाहरी संबंध सभी अनुवाद इकाइयों, बस पर विचार नहीं के साथ सभी समारोह घोषणाओं माना संबद्ध नामस्थान के भीतर देखने के लिए किया था मिलेगा उन घोषणाओं को टेम्पलेट परिभाषा और टेम्पलेट तत्काल संदर्भ में मिला, फिर कार्यक्रम में व्यवहार को अपरिभाषित किया गया है।

+0

मुझे लगता है कि मैं उन पैराग्राफ के कुछ हिस्सों को समझता हूं, लेकिन वे मेरे लिए थोड़ा अस्पष्ट हैं। मेरे पास केवल एक टीयू है और मेरे उदाहरण में कोई बाहरी संबंध कार्य नहीं है, मेरे द्वारा लिंक किए गए कोड से संबंधित अंतिम पैराग्राफ कैसा है? अगर मैं सही ढंग से समझता हूं, तो 'जादू' विधि पहले पैराग्राफ से जुड़ा हुआ है, लेकिन मुझे सटीक कारण समझने में कुछ परेशानी है। हालांकि मानक अंश के लिए बहुत बहुत धन्यवाद – Dante

संबंधित मुद्दे