मैंने आधुनिक टेम्पलेट प्रोग्रामिंग ( भाग I , भाग II ) के बारे में Cppcon14 में वाल्टर ब्राउन की चर्चा देखी , जहां उन्होंने अपनी void_t
SFINAE तकनीक प्रस्तुत की ।
उदाहरण:
एक सरल चर टेम्पलेट को देखते हुए जो मूल्यांकन करता है void
कि सभी टेम्पलेट तर्क अच्छी तरह से बने हैं:
template< class ... > using void_t = void;
और निम्नलिखित लक्षण जो सदस्य चर के अस्तित्व की जांच करता है जिसे सदस्य कहा जाता है :
template< class , class = void >
struct has_member : std::false_type
{ };
// specialized as has_member< T , void > or discarded (sfinae)
template< class T >
struct has_member< T , void_t< decltype( T::member ) > > : std::true_type
{ };
मैंने यह समझने की कोशिश की कि यह क्यों और कैसे काम करता है। इसलिए एक छोटा उदाहरण:
class A {
public:
int member;
};
class B {
};
static_assert( has_member< A >::value , "A" );
static_assert( has_member< B >::value , "B" );
1। has_member< A >
has_member< A , void_t< decltype( A::member ) > >
A::member
मौजूदdecltype( A::member )
अच्छी तरह से गठित हैvoid_t<>
मान्य है और इसका मूल्यांकन करता हैvoid
has_member< A , void >
और इसलिए यह विशेष टेम्पलेट चुनता हैhas_member< T , void >
और का मूल्यांकन करता हैtrue_type
2। has_member< B >
has_member< B , void_t< decltype( B::member ) > >
B::member
अस्तित्व में नहीं हैdecltype( B::member )
बीमार है और चुपचाप विफल रहता है (sfinae)has_member< B , expression-sfinae >
इसलिए इस टेम्पलेट को छोड़ दिया गया है
- संकलक
has_member< B , class = void >
डिफ़ॉल्ट तर्क के रूप में शून्य के साथ पाता है has_member< B >
का मूल्यांकन करता हैfalse_type
प्रश्न:
1. क्या मेरी यह समझ सही है?
2. वाल्टर ब्राउन का कहना है कि डिफ़ॉल्ट तर्क को ठीक उसी प्रकार का होना चाहिए जिस तरह void_t
से काम करने के लिए इसका उपयोग किया जाता है । ऐसा क्यों है? (मुझे नहीं पता कि इस प्रकार के मिलान की आवश्यकता क्यों है, क्या कोई डिफ़ॉल्ट प्रकार काम नहीं करता है?)
has_member< T , class = void >
डिफ़ॉल्ट होने की आवश्यकता नहीं दिखती है void
। मान लें कि इस विशेषता का उपयोग किसी भी समय केवल 1 टेम्पलेट तर्क के साथ किया जाएगा, तो डिफ़ॉल्ट तर्क किसी भी प्रकार का हो सकता है?
template <class, class = void>
गए template <class, class = void_t<>>
। इसलिए अब हम void_t
उर्फ टेम्पलेट कार्यान्वयन के साथ जो कुछ भी करना चाहते हैं, उसके लिए स्वतंत्र हैं :)
has_member<A,int>::value
:। फिर, आंशिक विशेषज्ञता जो कि मूल्यांकन करती हैhas_member<A,void>
, मेल नहीं खा सकती है। इसलिए, यहhas_member<A,void>::value
सिंथेटिक चीनी, प्रकार के एक डिफ़ॉल्ट तर्क के साथ, या होना चाहिएvoid
।