2015-03-13 5 views
5

मैं here प्रस्तुत दूसरे परिदृश्य को समझ नहीं सकता। इसे कहते हैं:enable_if एक फ़ंक्शन पैरामीटर जोड़ने के लिए जिसमें डिफ़ॉल्ट तर्क है?

• परिदृश्य 2: एक समारोह पैरामीटर एक डिफ़ॉल्ट तर्क है कि जोड़ना:

template <your_stuff> your_return_type_if_present 
yourfunction(args, enable_if_t<your condition, FOO> = BAR) { 
    // ... 
} 

परिदृश्य 2 पत्ते पैरामीटर अनाम। आप ::type Dummy = BAR कह सकते हैं, लेकिन नाम डमी अप्रासंगिक है, और इसे एक नाम देने से असुरक्षित पैरामीटर चेतावनी ट्रिगर करने की संभावना है। आपको FOO फ़ंक्शन पैरामीटर प्रकार और BAR डिफ़ॉल्ट तर्क चुनना होगा। आप int और 0 कह सकते हैं, लेकिन फिर आपके कोड के उपयोगकर्ता गलती से फ़ंक्शन को एक अतिरिक्त पूर्णांक पास कर सकते हैं जिसे अनदेखा किया जाएगा। इसके बजाय, हम अनुशंसा करते हैं कि आप void ** और या तो 0 या nullptr उपयोग करें, क्योंकि लगभग कुछ भी नहीं void ** के लिए परिवर्तनीय है:

template <your_stuff> your_return_type_if_present 
yourfunction(args, typename enable_if<your_condition, void **>::type=nullptr) { 
// ... 
} 

परिदृश्य 2 पैरामीटर तो क्या यह किया जा सकता है में अज्ञात छोड़ देता है? क्या इस काम को enable_if के साथ कोड बनाने का कोई तरीका है?

enum otype {oadd,omull}; 
template<otype o> 
int add(int num1, std::enable_if<o == oadd, int>::type int= num2) 
{ 
    if (o == omull) return num1 * num1; 
    if (o == oadd) return num1 + num2; 
} 
+0

जब (ab) उदाहरण के लिए अधिभार संकल्प का उपयोग कर यह उपयोगी हो सकता है: 10 मामले है कि आप अपने पोस्ट में पर इशारा किया है करने के लिए एक SFINAE समारोह टेम्पलेट पैरामीटर को लागू करने के लिए, आप की तरह लिखते थे। – BartoszKP

+0

'omull' भाग तक नहीं पहुंचा जा सकता है। – Jarod42

+0

enable_if फ़ंक्शन को सक्षम करता है, पैरामीटर नहीं। –

उत्तर

3

enable_if उदाहरण (अगर यह मदद करता है):

गैर शून्य वापसी प्रकार के साथ काम करता है के लिए:

एकल हालत के लिए:

template <template T, typename std::enable_if<!std::is_same<T,std::string>::value>::type* = nullptr > 
T func(T x){} 

कई के लिए हालत:

template <template T, typename std::enable_if<!std::is_same<T,std::string>::value &&!std::is_same<T,int>::value>::type* = nullptr > 
T func(T x){} 


शून्य वापसी प्रकार के साथ काम करता है के लिए:

एकल हालत के लिए:

template <template T> 
typename std::enable_if<!std::is_same<T,std::string>::value>::type 
func(T x){} 

कई हालत के लिए:

template <template T> 
typename std::enable_if<!std::is_same<T,std::string>::value &&!std::is_same<T,int>::value>::type 
func(T x){} 

शामिल करने के लिए #include <type_traits>

6

माइक्रोसॉफ्ट के प्रलेखन there वहाँ कीचड़ के रूप में स्पष्ट है मत भूलना। इसके बजाय this का उपयोग करें।

फार्म की एक अनाम डिफ़ॉल्ट पैरामीटर के साथ एक समारोह टेम्पलेट प्रदान करना: - केवल मामले में और -

typename enable_if<your_condition, void **>::type = nullptr 

(एमएस मुंशी पता चलता है के रूप में), मामले में उपयोगी है आप इच्छा के कई भार के लिखने के लिए विभिन्न व्यवहारों के साथ फ़ंक्शन टेम्पलेट जो टेम्पलेट तर्कों में से एक या अधिक द्वारा नियंत्रित होते हैं। फिर, एक शर्त टेम्पलेट तर्क (रों) पर एक उपयुक्त आवश्यकता व्यक्त करते your_condition की जगह, आप SFINAE सिद्धांत विशिष्ट अधिभार कि आप दिया टेम्पलेट तर्क के लिए instantiated होना चाहते हैं का चयन करने के भर्ती कर सकते हैं।

एसएफआईएनएई पैरामीटर - चलो इसे कॉल करें - तत्काल कार्य द्वारा अप्रयुक्त है; यह फ़ंक्शन टेम्पलेट ओवरलोड रिज़ॉल्यूशन में SFINAE को उत्तेजित करने के लिए पूरी तरह से मौजूद है। इसलिए यह नामहीन हो सकता है, और इसलिए इसे डिफ़ॉल्ट किया जाना चाहिए: आपको फ़ंक्शन टेम्पलेट का आह्वान करते समय इसे अतिरिक्त, बेकार, तर्क प्रदान करने के लिए मजबूर नहीं करना चाहिए।

उदाहरण के लिए:

#include <type_traits> 
#include <iostream> 

template <typename T> 
T foo(T && t, 
    typename std::enable_if<std::is_same<T,int>::value, void **>::type = nullptr) 
{ 
    std::cout << "Doubling " << t << " gives " << (t + t) << std::endl; 
    return t + t; 
} 

template <typename T> 
T foo(T && t, 
    typename std::enable_if<!std::is_same<T,int>::value, void **>::type = nullptr) 
{ 
    std::cout << "Squaring " << t << " gives " << (t * t) << std::endl; 
    return t * t; 
} 

using namespace std; 

int main() 
{ 
    cout << foo(2) << endl; 
    cout << foo(3.3) << endl; 
    return 0; 
} 

आउटपुट है:

Doubling 2 gives 4 
4 
Squaring 3.3 gives 10.89 
10.89 

समारोह टेम्पलेट foo के इन दो भार के अलावा, पहले एक दोगुना हो जाता है यह प्रकार T तर्क और दूसरा एक वर्ग अपने तर्क है, और एक SFINAE पैरामीटर का उपयोग यह निर्धारित करने के लिए किया जाता है कि दोगुना अधिभार तत्काल किया जाएगा यदि Tहैऔर स्क्वायर ओवरलोड अन्यथा चुना जाएगा।

जब Tint, शर्त है:

!std::is_same<T,int>::value 

कि बराबरी अधिभार की SFINAE पैरामीटर को नियंत्रित करता है गलत है। नतीजतन प्रकार निर्दिष्टकर्ता:

typename std::enable_if<!std::is_same<T,int>::value, void **>::type = nullptr 

संकलित करने के लिए विफल रहता है। यह टेम्पलेट रिज़ॉल्यूशन में प्रतिस्थापन विफलता है। int स्क्वायर ओवरलोड में T के लिए व्यवहार्य नहीं है। तो स्क्वायरिंग अधिभार चलने से समाप्त हो गया है, और केवल दोगुनी अधिभार को फ़ंक्शन कॉल को तुरंत चालू करने के लिए छोड़ा गया है।

जब T है (माना) double और नहीं int, तो बिल्कुल विपरीत होता है और केवल बराबरी अधिभार टेम्पलेट संकल्प बच जाता है। foo(2) पर कॉल करें और आपको दोगुना हो जाता है। foo(3.3) पर कॉल करें और आपको स्क्वायरिंग मिलती है।

यहां एमएस का नमूना SFINAE पैरामीटर अनिवार्य रूप से लंबा है।

template< bool B, class T = void > 
struct enable_if; 
प्रति सी ++ 11 मानक के रूप में और बाद में void करने के लिए

, चूक T। की तो जैसे:

typename std::enable_if<some_condition, void **>::type = nullptr 

रूप में अच्छी तरह संक्षिप्त किया जा सकता है:

typename std::enable_if<some_condition>::type * = nullptr 

और सी ++ 14 के रूप में मानक है:

template< bool B, class T = void > 
using enable_if_t = typename enable_if<B,T>::type 

तो एक ही SFINAE पैरामीटर कर सकते हैं आगे बढ़ाएं:

std::enable_if_t<some_condition> * = nullptr 
enum ops { 
    add, 
    multiply 
}; 

template<ops Op> 
int op(int const & lhs, int const & rhs, 
     std::enable_if_t<Op == add> * = nullptr) 
{ 
    return lhs + rhs; 
} 

template<ops Op> 
int op(int const & lhs, int const & rhs, 
     std::enable_if_t<Op == multiply> * = nullptr) 
{ 
    return lhs * rhs; 
} 

... 

auto i = op<add>(2,3); 
auto j = op<multiply>(2,3); 

... 
// C++14 
+0

धन्यवाद! अंततः मुझे SFINAE के लिए 'enable_if' का उपयोग करने के बारे में एक स्पष्ट स्पष्टीकरण मिला। आपका जवाब मुझे बहुत कुछ सीखने दो! संक्षेप में सभी तरह से 'std :: enable_if_t * = nullptr' वास्तव में सहायक है! मैं यह पूछना चाहता हूं कि 'शून्य **' से 'std :: enable_if :: type *' का संक्षिप्त नाम क्यों है, जिसे मैं सोचता हूं कि वास्तव में 'शून्य *' है? इसे उन्नत में सराहना करें। – astroboylrx

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