क्या आप वास्तव में टेम्पलेट परिभाषा के लिए उपयोग करते हैं, और नहीं, कहें, एक टेम्पलेट घोषणा (केवल)?
कुछ का उपयोग करता है:
// declaration only: the parameter name has no use beyond documentation
template<typename>
struct A;
// this is fine
template<typename T>
void eat_an_a(A<T> a);
// later, we can name the parameter to use it
template<typename T>
struct A { ... };
// C++0x only
template<
typename T
// We don't care for the actual type (which will default to void)
// the goal is sfinae
, typename = typename std::enable_if<
std::is_array<typename std::decay<T>::type>::value
>::value
>
void
f(T&& t);
// We still don't care to name that defaulted parameter
template<typename T, typename>
void f(T&& t)
{ ... }
बहुत विशेष मामले आप जोहानिस द्वारा दिया गया है से जुड़ा हुआ करने के लिए स्पष्टीकरण, लेकिन जाहिरा तौर पर आप इसे असंतोषजनक पाया है। मैं यह कैसे काम करता हूं के माध्यम से आपको चलने जा रहा हूं। हमें एक मनमाना लक्षण वर्ग मान लेते हैं:
// no definition
template<typename TypeToExamine, typename ImplementationDetail = void>
struct trait;
मैं उनके नाम में प्रकार पैरामीटर की भूमिका वर्तनी रहा हूँ। अब यह घोषणा क्या करती है, क्योंकि दूसरा पैरामीटर डिफॉल्ट किया गया है, सिंटैक्टिक चीनी का थोड़ा सा है। जहां भी trait<U>
प्रकट होता है, यह बिल्कुल जैसा कि हमने लिखा है trait<U, void>
लिखा गया था। हमें अब हमारे विशेषता के आधार मामले के लिए एक परिभाषा प्रदान करते हैं:
// assume previous declaration is still in scope so we do not default
// the second parameter again
template<typename T, typename> struct trait: std::false_type {};
यह एक बहुत ही उपयोगी विशेषता नहीं है। अब जब हम trait<U>
लिखते हैं, जो trait<U, void>
के लिए छोटा है, तो हम इस परिभाषा के साथ समाप्त होते हैं। इसका मतलब है कि trait<U>::value
मान्य है और वास्तव में false
है। की गुप्त संघटक जोड़कर हमारी कक्षा अधिक उपयोगी बनाने करते हैं:
template<typename> struct void_ { typedef void type; };
// again, assume previous declarations are in scope
template<typename T, typename void_<decltype(T() + T())>::type>
struct trait: std::true_type {};
फिर, जब हम trait<U>
लिखते हैं, यह के रूप में अगर हम trait<U, void>
लिखा था है। आंशिक विशेषज्ञता उसमें बदलाव नहीं करती है (इसकी अनुमति नहीं है)। लेकिन जब हम trait<U>::value
पर सवाल करते हैं तो हमें किस परिभाषा का उपयोग करना चाहिए? खैर, सबसे पहले, हमें यह जानना होगा कि विशेषज्ञता वास्तव में क्या है ... या, रहस्यमय दूसरा तर्क typename void_<decltype(T() + T())>::type
क्या है?
सबसे आसान मामला तब होता है जब U() + U()
खराब गठित होता है। फिर SFINAE में लाता है और ऐसा लगता है जैसे विशेषज्ञता मौजूद नहीं थी; इस प्रकार हम गैर-विशिष्ट परिभाषा प्राप्त करते हैं, और value
false
है। यदि U() + U()
अच्छी तरह से गठित है, तो decltype
एक प्रकार उत्पन्न करता है, और पूरे void
में बदल जाता है, क्योंकि सभी प्रकार void_<T>::type
void
है। तो इसका मतलब है कि हमारे पास फॉर्म trait<T, void>
का विशेषज्ञता है। यह trait<U>
से मेल खा सकता है, से U
के साथ मेल खाता है। और अब value
true
है।
यदि फिर भी विशेषज्ञता हैं
template<typename T>
struct trait<T, decltype(T() + T())>: std::true_type {};
लिखा गया है तो एक ही तरीका है यह इस्तेमाल किया जाएगा जब trait<U, decltype(U() + U())>
लेखन,decltype(U() + U())
जब तक शून्य होने के लिए happended। याद रखें, trait<U>
trait<U, void>
के लिए चीनी है। तो trait<int>
हमारी विशेषज्ञता से कभी मेल नहीं खाएगा क्योंकि बाद वाला फॉर्म trait<int, int>
है।
इस प्रकार void_
हमेशा trait<T, void>
फॉर्म की विशेषज्ञता रखने की भूमिका निभाता है यदि वे SFINAE'd नहीं हैं। चूंकि हम टाइप पैरामीटर का उपयोग करने की परवाह नहीं करते हैं, इसलिए इसका नाम नहीं है।
क्या आप विस्तार से विस्तार से विस्तार कर सकते हैं? – iammilind
@iammiling: वह कैसा है? –