दिलचस्प पोस्ट
एमवीसी एजेक्स जेसन पोस्ट नियंत्रक कार्रवाई विधि के लिए क्या आप नेस्ट एचटीएमएल फार्म कर सकते हैं? मिलान करने वाले फ़ंक्शन पॉइंटर को कॉल करने के लिए एक ट्यूपल को "अनपॅक करना" उस .CSS फ़ाइल के भीतर उपयोग के लिए .CSS फ़ाइल में एक वैरिएबल बनाएँ UIImagePickerController स्क्रीन को भर नहीं करता है MVC5 – DropDownListFor एचटीएमएल सहायक में "selectedValue" कैसे सेट करें जार में वर्ग फ़ाइल को अद्यतन करना जो अधिक सही है: <h1> <a> … </a> </ h1> या <a> <h1> … </ h1> </a> क्या मैं गिट में फास्ट फ़ॉरवर्डिंग बंद कर सकता हूं? यात्रा के समय डेटा प्राप्त करने के लिए Google मानचित्र API का उपयोग करना स्ट्रिंग को जावा में दूसरे स्थान पर कनवर्ट करें जेएस और जेक्यू एचटीएमएल तत्वों का पता लगा सकता है, और कहते हैं कि वे अपरिभाषित हैं इंस्टॉल किए गए एंड्रॉइड एप्लिकेशन की सूची प्राप्त करें X86 (-64) पर हस्ताक्षर किए गए और हस्ताक्षर किए गए गुणा करने के लिए अलग-अलग निर्देश क्यों हैं? एपाचे को 80 से अधिक पोर्ट पर सुनने के लिए कॉन्फ़िगर करें

std :: enable_if सशर्त एक सदस्य फ़ंक्शन को संकलित करने के लिए

मैं std::enable_if का उपयोग करने के तरीके को समझने के लिए काम करने के लिए एक सरल उदाहरण प्राप्त करने की कोशिश कर रहा हूं मैं इस उत्तर को पढ़ने के बाद, मैंने सोचा था कि यह एक सरल उदाहरण के साथ आने के लिए बहुत मुश्किल नहीं होना चाहिए। मैं दो सदस्यीय कार्यों के बीच चयन करने के लिए std::enable_if का उपयोग करना चाहता हूं और उनमें से केवल एक का उपयोग करने के लिए अनुमति देता हूं।

दुर्भाग्य से, निम्नलिखित जीसीसी 4.7 के साथ संकलन नहीं करता है और कोशिश करने के घंटे और घंटे के बाद मैं आपको लोगों से पूछ रहा हूं कि मेरी गलती क्या है।

 #include <utility> #include <iostream> template< class T > class Y { public: template < typename = typename std::enable_if< true >::type > T foo() { return 10; } template < typename = typename std::enable_if< false >::type > T foo() { return 10; } }; int main() { Y< double > y; std::cout << y.foo() << std::endl; } 

जीसीसी निम्नलिखित समस्याओं की रिपोर्ट करता है:

 % LANG=C make CXXFLAGS="-std=c++0x" enable_if g++ -std=c++0x enable_if.cpp -o enable_if enable_if.cpp:12:65: error: `type' in `struct std::enable_if<false>' does not name a type enable_if.cpp:13:15: error: `template<class T> template<class> TY::foo()' cannot be overloaded enable_if.cpp:9:15: error: with `template<class T> template<class> TY::foo()' 

दूसरे सदस्य फ़ंक्शन के लिए गलत तात्कालिकता क्यों नहीं जी ++ हटाएं? मानक के अनुसार, std::enable_if< bool, T = void >::type केवल तब होता है जब बूलियन टेम्पलेट पैरामीटर सही है लेकिन जी ++ इस पर एसएफआईएनएई के रूप में क्यों नहीं सोचता? मुझे लगता है कि ओवरलोडिंग त्रुटि संदेश समस्या से आता है जो जी ++ दूसरे सदस्य फ़ंक्शन को नहीं हटाता है और मानता है कि यह अधिभार होना चाहिए।

वेब के समाधान से एकत्रित समाधान "std :: enable_if सशर्त एक सदस्य फ़ंक्शन को संकलित करने के लिए"

SFINAE केवल तभी काम करता है जब एक टेम्पलेट तर्क के तर्क कटाव में प्रतिस्थापन का निर्माण गलत रूप से निर्मित होता है। ऐसी कोई प्रतिस्थापन नहीं है

मैंने उस बारे में भी सोचा और std::is_same< T, int >::value और उपयोग करने की कोशिश की ! std::is_same< T, int >::value ! std::is_same< T, int >::value जो समान परिणाम देता है

इसका कारण यह है कि जब क्लास टेम्प्लेट तत्काल होता है (जो तब होता है जब आप किसी अन्य प्रकार के किसी भी प्रकार के Y<int> को बनाते हैं), यह अपने सभी सदस्य घोषणाओं को शुरू करता है (जरूरी नहीं कि उनकी परिभाषाएं / निकायों!)। उनमें से इसके सदस्य टेम्पलेट भी हैं। ध्यान दें कि T तब जाना जाता है, और !std::is_same< T, int >::value पैदावार गलत है तो यह एक वर्ग Y<int> जिसमें है

 class Y<int> { public: /* instantiated from template < typename = typename std::enable_if< std::is_same< T, int >::value >::type > T foo() { return 10; } */ template < typename = typename std::enable_if< true >::type > int foo(); /* instantiated from template < typename = typename std::enable_if< ! std::is_same< T, int >::value >::type > T foo() { return 10; } */ template < typename = typename std::enable_if< false >::type > int foo(); }; 

std::enable_if<false>::type एक गैर-मौजूदा प्रकार तक पहुँचता है, ताकि घोषणा खराब हो। और इस प्रकार आपका प्रोग्राम अमान्य है

आपको सदस्य टेम्पलेट बनाने की ज़रूरत है ' enable_if सदस्य टेम्पलेट के एक पैरामीटर पर निर्भर करती है। तब घोषणाएं मान्य हैं, क्योंकि संपूर्ण प्रकार अभी भी निर्भर है। जब आप इनमें से किसी एक को कॉल करने का प्रयास करते हैं, उनके टेम्पलेट तर्कों के लिए तर्क कटौती होती है और अपेक्षित होने के साथ SFINAE होता है यह सवाल और इसी तरह उत्तर दें कि यह कैसे करना है।

मैंने यह छोटा उदाहरण बनाया है जो काम करता है

 #include <iostream> #include <type_traits> class foo; class bar; template<class T> struct check { template<class Q = T> typename std::enable_if<std::is_same<Q, bar>::value, bool>::type test() { return true; } template<class Q = T> typename std::enable_if<!std::is_same<Q, bar>::value, bool>::type test() { return false; } }; int main() { check<foo> check_foo; check<bar> check_bar; if (!check_foo.test() && check_bar.test()) std::cout << "It works!" << std::endl; return 0; } 

यदि आप मुझे विस्तृत करना चाहते हैं तो टिप्पणी करें मुझे लगता है कि कोड अधिक या कम आत्म-व्याख्यात्मक है, लेकिन फिर मैंने इसे बनाया ताकि मैं गलत हो जाऊंगा 🙂

आप यहां कार्रवाई में इसे देख सकते हैं।

उन देर से आने वाले लोगों के लिए जो "बस काम करता है" एक समाधान की तलाश कर रहे हैं:

 #include <utility> #include <iostream> template< typename T > class Y { template< bool cond, typename U > using resolvedType = typename std::enable_if< cond, U >::type; public: template< typename U = T > resolvedType< true, U > foo() { return 11; } template< typename U = T > resolvedType< false, U > foo() { return 12; } }; int main() { Y< double > y; std::cout << y.foo() << std::endl; } 

संकलन:

 g++ -std=gnu++14 test.cpp 

रनिंग देता है:

 ./a.out 11 

इस पोस्ट से:

डिफ़ॉल्ट टेम्पलेट तर्क एक टेम्पलेट के हस्ताक्षर का हिस्सा नहीं हैं

लेकिन कोई ऐसा कुछ कर सकता है:

 #include <iostream> struct Foo { template < class T, class std::enable_if < !std::is_integral<T>::value, int >::type = 0 > void f(const T& value) { std::cout << "Not int" << std::endl; } template<class T, class std::enable_if<std::is_integral<T>::value, int>::type = 0> void f(const T& value) { std::cout << "Int" << std::endl; } }; int main() { Foo foo; foo.f(1); foo.f(1.1); // Output: // Int // Not int } 

इस समस्या को सुलझाने का एक तरीका, सदस्य कार्यों का विशेषज्ञता किसी अन्य वर्ग में विशेषज्ञता रखना है, फिर उस कक्षा से प्राप्त होता है। आपको अन्य सभी अंतर्निहित डेटा तक पहुंच प्राप्त करने के लिए वारिसन के क्रम को बदलना पड़ सकता है लेकिन यह तकनीक काम करती है।

 template< class T, bool condition> struct FooImpl; template<class T> struct FooImpl<T, true> { T foo() { return 10; } }; template<class T> struct FoolImpl<T,false> { T foo() { return 5; } }; template< class T > class Y : public FooImpl<T, boost::is_integer<T> > // whatever your test is goes here. { public: typedef FooImpl<T, boost::is_integer<T> > inherited; // you will need to use "inherited::" if you want to name any of the // members of those inherited classes. }; 

इस तकनीक का नुकसान यह है कि यदि आपको अलग-अलग सदस्य कार्यों के लिए कई अलग-अलग चीजों का परीक्षण करने की ज़रूरत होती है तो आपको प्रत्येक के लिए एक वर्ग बनाना होगा, और वारिसेंस ट्री में इसे चेन करना होगा। आम डेटा सदस्यों तक पहुंचने के लिए यह सच है।

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

 template<class T, bool condition> class Goo; // repeat pattern above. template<class T, bool condition> class Foo<T, true> : public Goo<T, boost::test<T> > { public: typedef Goo<T, boost::test<T> > inherited: // etc. etc. }; 

बूलीयन को टेम्प्लेट पैरामीटर पर आधारित होने की आवश्यकता होती है। इसलिए तय करने का एक आसान तरीका डिफ़ॉल्ट बूलियन पैरामीटर का उपयोग करना है:

 template< class T > class Y { public: template < bool EnableBool = true, typename = typename std::enable_if<( std::is_same<T, double>::value && EnableBool )>::type > T foo() { return 10; } }; 

हालांकि, यह कार्य नहीं करेगा यदि आप सदस्य फ़ंक्शन को ओवरलोड करना चाहते हैं। इसके बजाए, टिक लाइब्रेरी से TICK_MEMBER_REQUIRES का उपयोग करना सबसे अच्छा है:

 template< class T > class Y { public: TICK_MEMBER_REQUIRES(std::is_same<T, double>::value) T foo() { return 10; } TICK_MEMBER_REQUIRES(!std::is_same<T, double>::value) T foo() { return 10; } }; 

आप अपने स्वयं के सदस्य को भी लागू कर सकते हैं इस तरह मैक्रो की जरूरत है (सिर्फ अगर आप किसी अन्य पुस्तकालय का उपयोग नहीं करना चाहते हैं):

 template<long N> struct requires_enum { enum class type { none, all }; }; #define MEMBER_REQUIRES(...) \ typename requires_enum<__LINE__>::type PrivateRequiresEnum ## __LINE__ = requires_enum<__LINE__>::type::none, \ class=typename std::enable_if<((PrivateRequiresEnum ## __LINE__ == requires_enum<__LINE__>::type::none) && (__VA_ARGS__))>::type