2012-08-17 20 views
6

मेरे पास निम्न कोड है जो संकलित नहीं करता है। यह एक टेम्पलेट वर्ग है कि तर्कटेम्पलेट विधि enable_if विशेषज्ञता

typename std::enable_if<std::is_void<Ret>::value, Ret>::type _on_dispatched() { 
    // ... 
} 

typename std::enable_if<!std::is_void<Ret>::value, Ret>::type _on_dispatched() { 
    // .... 
} 

मैं पर किस प्रकार Ret है निर्भर करता है एक सदस्य विधि में विशेषज्ञता चाहते लेता में दो कार्य कर रहे हैं।

क्या किसी को कुछ विचार है?

उत्तर

7

SFINAE गैर-टेम्पलेट फ़ंक्शंस (सदस्य या गैर-सदस्य) पर काम नहीं करता है।

जैसा कि केरेक एसबी बताता है, उन्हें गैर-सदस्यीय फ़ंक्शन टेम्पलेट्स काम करेंगे। या जैसे ज़ीओ बताते हैं, उन्हें डिफॉल्ट टेम्पलेट तर्क के साथ सदस्य फ़ंक्शन टेम्पलेट्स बनाना भी काम करेगा।

हालांकि, यह केवल काम कर रहा है क्योंकि दो std::enable_if स्थितियां गैर-ओवरलैपिंग हैं। यदि आप int (कहें) के लिए एक अलग ओवरलोड जोड़ना चाहते हैं, तो आप पाएंगे कि यह अच्छी तरह से स्केल नहीं करता है।

#include<type_traits> 

template<typename Ret> 
class Foo 
{ 
public: 
    void _on_dispatched() 
    { 
     // tag dispachting: create dummy of either std::false_type or std::true_type 
     // almost guaranteed to be optimized away by a decent compiler 
     helper_on_dispatched(std::is_void<Ret>()); 
    } 

private: 
    void helper_on_dispatched(std::false_type) 
    { 
     // do stuff for non-void 
    } 

    void helper_on_dispatched(std::true_type) 
    { 
     // do stuff for void 
    } 
}; 

int main() 
{ 
    Foo<void>()._on_dispatched(); 
    Foo<int>()._on_dispatched(); 
    return 0; 
} 
+1

आप कर सकते हैं, अगर भार के में से एक कॉल समय में केवल व्यवहार्य एक है। :) http://liveworkspace.org/code/fd6e5383610d4e0d8fb17c5497991355 – Xeo

+1

@ पोटाटोस्वाटर: वास्तव में, नहीं, यह एक मजाक नहीं था। लिंक देखें, आप बिल्कुल ठीक उसी हस्ताक्षर के साथ एक फ़ंक्शन कर सकते हैं जहां केवल वापसी प्रकार तय करता है कि यह व्यवहार्य है या नहीं। : पी इसके अलावा, बस 'std :: is_void () 'का उपयोग करें, टाइप टाइप्स को' std :: true_type' या 'std :: false_type' से प्राप्त करने के लिए आवश्यक हैं। – Xeo

+1

बीटीडब्ल्यू, [आप सदस्य को सी ++ 11 में डिफ़ॉल्ट पैरामीटर के साथ टेम्पलेट को फ़ंक्शन कर सकते हैं] (http://liveworkspace.org/code/781d94df5499998947217970c1aebf2a)। – Xeo

3

SFINAE केवल टेम्पलेट्स पर काम करता है: क्या आप क्या करना चाहते के आधार पर, टैग भेजने आम तौर पर कई विकल्प है कि आप पर प्रेषण करने के लिए चाहते हैं के साथ SFINAE की तुलना में बेहतर मापता है। आपका कोड एक छोटा सा संशोधन के साथ संकलित करने के लिए बनाया जा सकता है:

template <typename Ret> 
typename std::enable_if<std::is_void<Ret>::value, Ret>::type _on_dispatched() { /*...*/ } 

template <typename Ret> 
typename std::enable_if<!std::is_void<Ret>::value, Ret>::type _on_dispatched() { /*...*/ } 

उपयोग:

auto q = _on_dispatched<int>(); 

आप निश्चित रूप से एक समारोह की वापसी प्रकार, अनुमान नहीं कर सकते, क्योंकि यह निगम्य नहीं है। हालांकि, अगर आप अन्य टेम्पलेट अंदर इस टेम्पलेट पैक कर सकते हैं:

template <typename T> 
struct Foo 
{ 
    // insert templates here, maybe privately so 

    T bar() { return _on_dispatched<T>(); } 
}; 
+0

'टेम्पलेट <वर्ग आरएक्स = रेट>', rhalbersma के उत्तर पर मेरी टिप्पणी देखें। – Xeo

+0

@Xeo: आपका मतलब है कि हमें '' लिखने से बचाएगा? जरूर, क्यों नहीं :-) –

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

  • कोई संबंधित समस्या नहीं^_^