2016-09-15 16 views
5

मैं सी ++ टेम्पलेट का चयन करने के तरीके को समझने की कोशिश कर रहा हूं।सदस्य फ़ंक्शन टेम्पलेट चयन और SFINAE

template <typename R> 
class Curious 
{ 
public: 
    template <typename T, typename std::enable_if<std::is_const<T>::value, int>::type = 33> 
    void test1() {} 

    template <typename T, typename std::enable_if<!std::is_const<T>::value, int>::type = 33> 
    void test1() {} 

    template <typename T, typename = typename std::enable_if<std::is_const<T>::value>::type> 
    void test2() {} 

    template <typename T, typename = typename std::enable_if<!std::is_const<T>::value>::type> 
    void test2() {} 

    template <typename std::enable_if<std::is_const<R>::value>::type * = nullptr> 
    void test3() {} 

    template <typename std::enable_if<!std::is_const<R>::value>::type * = nullptr> 
    void test3() {} 

    // works 
    template <typename T = void> 
    typename std::enable_if<std::is_const<R>::value, T>::type test4() {} 

    template <typename T = void> 
    typename std::enable_if<!std::is_const<R>::value, T>::type test4() {} 

    // also works 
    template <typename T = void, typename std::enable_if<std::is_const<R>::value, T>::type * = nullptr> 
    void test5() {} 

    template <typename T = void, typename std::enable_if<!std::is_const<R>::value, T>::type * = nullptr> 
    void test5() {} 
}; // Curious 

पहले दो कार्य (test1) ठीक से काम (क्यों?):

Curious<int> curious; 
curious.test1<int>(); 
curious.test1<const int>(); 

जबकि संकलन त्रुटियों कारण उनमें से बाकी अर्थात्, निम्नलिखित कोड नमूना पर विचार करें। संकलक दावों मैं एक नकली बनाने के लिए कोशिश कर रहा हूँ test2 समारोह के बारे में:

error C2535: 'void Curious::test2(void)': member function already defined or declared

Here प्रलेखन कहते हैं:

एक आम गलती दो समारोह टेम्पलेट्स है कि केवल में मतभेद घोषित करने के लिए है उनके डिफ़ॉल्ट टेम्पलेट तर्क। यह अवैध है क्योंकि डिफ़ॉल्ट टेम्पलेट तर्क फ़ंक्शन टेम्पलेट के हस्ताक्षर का हिस्सा नहीं हैं, और एक ही हस्ताक्षर के साथ दो अलग-अलग फ़ंक्शन टेम्पलेट्स घोषित करना अवैध है।

तो ऐसा लगता है। हालांकि, मुझे पहले दो कार्यों से बहुत अंतर दिखाई नहीं देता है, जिसमें डिफ़ॉल्ट टेम्पलेट तर्क भी है। इस प्रकार हमारे पास डिफ़ॉल्ट मान (test1 - works) के विरुद्ध एक डिफ़ॉल्ट प्रकार (test2 - काम नहीं करता) है। क्या इसके बारे में कोई नियम है?

test3:

error C2039: 'type': is not a member of 'std::enable_if'
के मामले में पहली बार इस तरह के सदस्य फ़ंक्शन टेम्पलेट में डिफ़ॉल्ट गैर-प्रकार पैरामीटर होता है, लेकिन यह क्लास टेम्पलेट पैरामीटर पर निर्भर करता है। अब SFINAE गलत को छोड़ नहीं देता है (यह भी सुनिश्चित नहीं है)।

चौथे मामले में SFINAE रिटर्न प्रकार से टेम्पलेट को हल करता है। लेकिन क्या इन test4 कार्यों में समान हस्ताक्षर नहीं है? क्योंकि वे केवल रिटर्न प्रकार में भिन्न होते हैं।

जहां तक ​​मैं समझता हूं, पांचवें मामले में अतिरिक्त पैरामीटर जोड़ना फ़ंक्शन टेम्पलेट पैरामीटर पर test5 हस्ताक्षर निर्भर करता है, इसलिए SFINAE में और रिज़ॉल्यूशन काम करता है।

मैं इस टेम्पलेट्स के साथ सी ++ सौदों के बारे में काफी उलझन में हूं। क्या कोई इन चीज़ों को साफ़ करने के लिए बहुत दयालु हो सकता है?

+1

एक नोट के रूप में, के बाद से सी ++ 14, आप की जगह ले सकती 'typename std :: enable_if :: type'' std :: enable_if_t 'द्वारा। – Jarod42

उत्तर

6
  • डिफ़ॉल्ट मान हटा दिया साथ, test1 के लिए, आपके पास:

    template <typename T, typename std::enable_if<std::is_const<T>::value, int>::type> 
    void test1(); 
    
    template <typename T, typename std::enable_if<!std::is_const<T>::value, int>::type> 
    void test1(); 
    

    स्पष्ट रूप से अलग हस्ताक्षर है कौन सा।

  • test2 के लिए:

    template <typename T, typename> void test2(); 
    
    template <typename T, typename> void test2(); 
    

    जो स्पष्ट रूप से समान हस्ताक्षर कर रहे हैं।

  • test3 के लिए, SFINAE लागू नहीं होता है क्योंकि आपको कठिनाई होती है क्योंकि R कक्षा में तय किया गया है और आपके enable_if फ़ंक्शन के टेम्पलेट पैरामीटर पर निर्भर नहीं है।

  • test4 के लिए, वहाँ टेम्पलेट समारोह के लिए हस्ताक्षर के बारे में एक अपवाद के रूप अधिभार केवल वापसी प्रकार से भिन्न हो सकती है इसलिए

    int foo(); 
    char foo(); // Illegal. 
    

    लेकिन

    template <typename T> int foo(); 
    template <typename T> char foo(); // legal, even it is not trivial to call 
    

    इसके अलावा, std::enable_if<!std::is_const<R>::value, T>::type टेम्पलेट पैरामीटर T पर निर्भर करता है तो यह ठीक है।

  • test5 के लिए, दूसरा टेम्पलेट पैरामीटर पहले टेम्पलेट पैरामीटर T पर निर्भर करता है, इसलिए यह भी ठीक है।

+0

धन्यवाद, मैंने अभी अपनी मूल पोस्ट – mentalmushroom

+0

में दो और उदाहरण जोड़े हैं test4/test5 के लिए जोड़ा गया स्पष्टीकरण: 'enable_if' दोनों मामलों में' टी' पर निर्भर करता है। – Jarod42

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