2016-04-12 15 views
6

सी ++ 11 विशेषज्ञों के लिए सवालों की एक जोड़ी के साथ अलग व्यवहार।जी ++ और बजना ++ SFINAE और SFINAE विफलता

मैं SFINAE के साथ लड़ रहा हूँ और मैं एक अजीब मामला भर में आया था जो जी ++ (4.9.2), और बजना में ++ (3.5.0) अलग तरीके से व्यवहार।

मैं निम्न नमूना कोड तैयार किया है। मुझे खेद है, लेकिन मैं इसे काफी संक्षिप्त करने में असमर्थ हूं।

#include <string> 
#include <iostream> 
#include <typeinfo> 
#include <type_traits> 

template <typename X> 
class foo 
{ 
    private: 
     template <typename R> 
     using enableIfIsInt 
     = typename std::enable_if<std::is_same<X, int>::value, R>::type; 

    public: 
     foo() 
     { } 

     template <typename R = void> 
     enableIfIsInt<R> bar() 
      { std::cout << "bar: is int\n"; } 

     void bar() 
     { 
     std::cout << "bar: isn't int; is [" << typeid(X).name() << "]{" 
      << typeid(enableIfIsInt<void>).name() << "}\n"; 
     } 
}; 


int main() 
{ 
    foo<long> fl; 
    foo<int> fi; 

    fl.bar(); 
    fi.bar(); 

    return 0; 
} 

मेरा विचार एक टेम्पलेट foo<X> वर्ग (SFINAE के माध्यम से) से एक में या X टेम्पलेट तर्क के आधार पर किसी अन्य तरीके से एक विधि को परिभाषित कर सकते बनाने के लिए किया गया था।

कार्यक्रम छ ++ 4.9.2 लेकिन बजना के साथ अच्छी तरह से संकलन ++ 3.5.0 निम्न त्रुटि

test.cpp:13:36: error: no type named 'type' in 
     'std::__1::enable_if<false, void>'; 'enable_if' cannot be used to disable 
     this declaration 
     = typename std::enable_if<std::is_same<X, int>::value, R>::type; 
           ^~~~~~~~~~~~~~~~~~~~~~~~~~~ 
test.cpp:26:23: note: in instantiation of template type 
     alias 'enableIfIsInt' requested here 
      << typeid(enableIfIsInt<void>).name() << "}\n"; 
        ^
test.cpp:36:7: note: in instantiation of member function 
     'foo<long>::bar' requested here 
    fl.bar(); 
    ^
1 error generated. 

देना मुझे लगता है कि सही बजना ++ लेकिन सी ++ 11 विशेषज्ञों का मेरा पहला सवाल है: जो है ना? जी ++ या क्लैंग ++?

जी ++ का उत्पादन कार्यक्रम उत्पादन के बारे में, यह निम्न

bar: isn't int; is [i]{v} 

तो जी ++ fl.bar(); अनुदेश उपेक्षा करने लगता है।

अब एक छोटे से परिवर्तन: मैं इस तरह से

void bar() 
    { std::cout << "bar: isn't int; is [" << typeid(X).name() << "]\n"; } 

std::enable_if समारोह abomination अंदर को हटाने में foo<X>::bar() के दूसरे संस्करण को संशोधित। अब दोनों जी ++ और बजना ++, समस्याओं और उत्पादन कार्यक्रम के दोनों संस्करणों के लिए संकलित, बिना संकलन हैं

bar: isn't int; is [l] 
bar: isn't int; is [i] 

तो है, मेरी दूसरी सवाल यह है: मैं गलत क्या कर रहा हूँ? क्यों, int मामले में, मुझे foo<X>::bar() का "is int" संस्करण प्राप्त नहीं हुआ है? मैं सी ++ 11 जानने के लिए कोशिश कर रहा हूँ:

मेरे साथ रोगी अगर मैं कुछ मूर्ख कर रहा हूँ है।

और मेरी खराब अंग्रेजी के लिए खेद है।

+1

आप एक और अधिक हाल ही बजना संस्करण के साथ इस की कोशिश की है और एक और हालिया जीसीसी (जैसे 5.3)? शायद निर्देशक हो सकता है ... –

+0

अधिकतर कम से कम repro: http://coliru.stacked-crooked.com/a/713fbbbca7e8b8c5। मैं कैशिंग को दोषी ठहराता हूं। –

+2

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70642 –

उत्तर

6

बजना की त्रुटि प्रतिस्थापन विफलता से नहीं आ रही है। यह यहाँ से आ रहा है:

void bar() 
    { 
    std::cout << "bar: isn't int; is [" << typeid(X).name() << "]{" 
     << typeid(enableIfIsInt<void>).name() << "}\n"; // <== 
    } 

enableIfIsInt<void> तत्काल संदर्भ में नहीं है, कि X के लिए एक कठिन विफलता है नहीं int है। आप उस संदर्भ में उस अभिव्यक्ति का उपयोग नहीं कर सकते हैं।

एक बार जब आप कि को दूर - गैर टेम्पलेट bar() हमेशा कहा जाता है। ऐसा इसलिए है क्योंकि दोनों फ़ंक्शन समकक्ष मिलान हैं और गैर-टेम्पलेट्स को ओवरलोड रिज़ॉल्यूशन में टेम्पलेट्स के लिए प्राथमिकता दी जाती है।

void bar() { bar(std::is_same<X, int>{}); } 

void bar(std::true_type) { 
    std::cout << "bar: is int\n"; 
} 

void bar(std::false_type) { 
    std::cout << "bar: isn't int; is [" << typeid(X).name() << "]\n"; 
} 

जिसके साथ दोनों compilers खुशी से उपज:

तो असली समाधान का उपयोग करने टैग भेजने में है (जैसे 3,8)

bar: isn't int; is [l] 
bar: is int 
+0

जो मैंने केंद्रित नहीं किया था वह था कि गैर-टेम्पलेट्स को ओवरलोड रिज़ॉल्यूशन में टेम्पलेट्स को प्राथमिकता दी जाती है; धन्यवाद। – max66

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