2015-12-26 11 views
5

मैंने यह कोड देखने के लिए यह कोड लिखा है कि कक्षा के प्रकार में begin फ़ंक्शन है।इस मामले में ओवरलोड रिज़ॉल्यूशन क्यों अस्पष्ट है?

struct foo //a simple type to check 
{ 
    int begin(){ return 0;} 
}; 

struct Fallback 
{ 
    int begin(){ return 0;} 
}; 

template<typename T> 
struct HasfuncBegin : T,Fallback 
{ 
    typedef char one; 
    typedef int two; 

    template<typename X> 
    static one check(int (X::*)() = &HasfuncBegin<T>::begin); 
    template<typename X> 
    static two check(...); 

    enum :bool {yes = sizeof(check<T>())==1, no= !yes}; 
}; 

int main() 
{ 
    std::cout<< HasfuncBegin<foo>::yes; 
    return 0; 
} 

कौन सा पैदा करता है त्रुटि:

error: call of overloaded 'check()' is ambiguous 
    enum {yes = sizeof(check<T>())==1, no= !yes}; 
           ^
C:\XXX\main.cpp:24:16: note: candidate: static HasfuncBegin<T>::one HasfuncBegin<T>::check(int (X::*)()) [with X = foo; T = foo; HasfuncBegin<T>::one = char] 
    static one check(int (X::*)() = &HasfuncBegin<T>::begin); 
       ^
C:\XXX\main.cpp:26:16: note: candidate: static HasfuncBegin<T>::two HasfuncBegin<T>::check(...) [with X = foo; T = foo; HasfuncBegin<T>::two = int] 
    static two check(...); 


     ^

किसी को भी कृपया समझा क्यों कॉल अस्पष्ट (प्रयोग की जाने वाली भले ही हस्ताक्षर one check(int (X::*)() = &HasfuncBegin<T>::begin); साथ पहली जांच समारोह डिफ़ॉल्ट तर्क है) है और भी कैसे मेरे कोड बनाने के लिए काम?

संपादित करें:

struct foo 
{ 
    int begin(){ return 0;} 
}; 

struct Fallback 
{ 
    int begin(){ return 0;} 
}; 

template<typename T, T ptr> struct dummy{}; 

template<typename T> 
struct HasfuncBegin : T,Fallback 
{ 
    typedef char one; 
    typedef int two; 


    template<typename X> 
    static one check(dummy<int (X::*)(),&HasfuncBegin<X>::begin>*); 
// even this won't work, so replace above statement with below commented one 
// static one check(dummy<decltype(&HasfuncBegin<X>::begin),&HasfuncBegin<X>::begin>*); 
    template<typename X> 
    static two check(...); 

    enum {yes = sizeof(check<T>(0))==1, no= !yes}; 
}; 
+0

तरह 'typename std :: सशर्त कुछ क्यों उपयोग नहीं :: मान, एक, दो> :: टाइप'? –

+0

डिफ़ॉल्ट फ़ंक्शन तर्क फ़ंक्शन हस्ताक्षर का हिस्सा नहीं हैं और SFINAE द्वारा नहीं माना जाता है। – cpplearner

+0

http://stackoverflow.com/q/257288/1639256 या http://stackoverflow.com/q/1966362/1639256 – Oktalist

उत्तर

0

कॉल संदिग्ध है क्योंकि ओवरलोड चयन कॉल पैरामीटर से फ़ंक्शन पैरामीटर में रूपांतरण अनुक्रमों पर आधारित है। नियम थोड़ा जटिल यहां पूरी तरह समझाने के लिए हैं, लेकिन इन दो उदाहरणों पर विचार करें:

void ex1(int) {} //v1 
void ex1(...) {} //v2 

void ex2(int = 1) {} //v1 
void ex2(...) {} //v2 

int main() { 
    ex1(1); 
    ex2(); 
} 

ex1(1) कॉल अच्छी तरह से गठित है। एक एकल तर्क है जिसमें (सटीक मिलान बनाम इलिप्सिस रूपांतरण) से v1 पर बेहतर अंतर्निहित रूपांतरण अनुक्रम है।

ex2() कॉल खराब गठित है। रूपांतरण अनुक्रमों की तुलना करने के लिए कोई तर्क नहीं है और दोनों ओवरलोड को कोई तर्क नहीं कहा जा सकता है। यह आपके कोड के समान है।


ऐसा लगता है कि सी ++ 03 के साथ फंस रहे हैं, इसलिए यहां एक संभव समाधान this answer का उपयोग कर रहा है:

template<typename T>        
struct HasfuncBegin {              
    typedef char yes[1];            
    typedef char no [2];            
    template <typename U, U> struct type_check;      
    template <typename _1> static yes &chk(type_check<int (T::*)(), &_1::begin > *); 
    template <typename > static no &chk(...);      
    static bool const value = sizeof(chk<T>(0)) == sizeof(yes);  
}; 

Live Demo

+0

क्या आप फ़ॉलबैक तंत्र का उपयोग करके अपना कोड सही कर सकते हैं जिसे मैं उपयोग करने का प्रयास कर रहा था? धन्यवाद) –

+0

मैं पूरी तरह समझ नहीं पा रहा हूं कि फॉलबैक क्या है। क्या आप 'HasfuncBegin' से विरासत में होने की योजना बना रहे हैं ताकि आप डिफ़ॉल्ट प्राप्त कर सकें यदि आपके द्वारा निर्दिष्ट कक्षा में कोई नहीं है? – TartanLlama

+0

बीटीडब्ल्यू मूल प्रश्न में टिप्पणी: "आप भी SFINAE नहीं कर रहे हैं क्योंकि कोई टेम्पलेट तर्क नहीं लिया जा रहा है" आपको सर समझ में आता है? धन्यवाद –

3

अस्पष्टता के लिए कारण है कि दोनों (टेम्प्लेट की गई) check() के भार के check<T>() के लिए मान्य मैचों हैं:

तो यहाँ अंतिम काम कर कोड है। आपको लगता है कि एक दूसरे की तुलना में अधिक मान्य है लेकिन भाषा के नियम यह है कि वे दोनों समान रूप से मान्य हैं।

एक परिवर्तनीय तर्क फ़ंक्शन (...) शून्य या अधिक तर्कों के लिए एक मिलान है (यानी check<T>())। एक तर्क के साथ एक फ़ंक्शन जिसमें डिफ़ॉल्ट मान होता है check<T>() से मेल खाता है।

इसलिए अस्पष्टता के बारे में संदेश।

आपने वास्तव में वर्णन नहीं किया है कि आप इस कोड के साथ क्या हासिल करने की कोशिश कर रहे हैं (विशेष रूप से enum का प्रारंभिकरण), लेकिन किसी भी तरह से उम्मीद है कि हम जो भी करने की कोशिश कर रहे हैं, हम काम करेंगे। इसे संकलित करने का स्पष्ट तरीका ओवरलोड में से एक को हटाना होगा।

लेकिन, जब तक आप वर्णन नहीं करते कि आप वास्तव में क्या हासिल करने की कोशिश कर रहे हैं, कोई भी आपको सलाह नहीं दे सकता है। इस तरह की साइटों को पढ़ने से लोगों को दिमाग की शक्तियां नहीं मिलती हैं।

+0

कोई टेम्पलेट तर्क नहीं लिया जा रहा है ' मैं प्राप्त करने की कोशिश कर रहा हूं प्रश्न की पहली पंक्ति में लिखा गया है: 'मैंने इस कोड को यह जांचने के लिए लिखा है कि कक्षा प्रकार शुरू हो गया है या नहीं। –

+0

और वह विवरण अपर्याप्त है। माफ़ कीजिये। – Peter

+0

@ पीटर कोड से स्पष्ट नहीं है? यदि 'प्रारंभ() 'सदस्य फ़ंक्शन मौजूद है, तो enum में' yes' सत्य होना चाहिए। ओवरलोड रिज़ॉल्यूशन के आधार पर एक या अन्य 'चेक() 'चुना जाता है, जिससे' हां 'के लिए एक अलग मूल्य होता है (काम नहीं करता है, लेकिन यह विचार था)। –

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