15

मैं इस स्रोत कोडकोड मैं में सी ++ 11

template<char... digits> 
struct conv2bin; 

template<char high, char... digits> 
struct conv2bin<high, digits...> { 
    static_assert(high == '0' || high == '1', "no bin num!"); 
    static int const value = (high - '0') * (1 << sizeof...(digits)) + 
          conv2bin<digits...>::value; 
}; 

template<char high> 
struct conv2bin<high> { 
    static_assert(high == '0' || high == '1', "no bin num!"); 
    static int const value = (high - '0'); 
}; 

template<char... digits> 
constexpr int operator "" _b() { 
    return conv2bin<digits...>::value; 
} 

int array[1010_b]; 

पर देख रहा हूँ कभी नहीं देखा है और मैं अगर यह भी वैध C++ है सोच रहा हूँ।

template<char high, char... digits> 
struct conv2bin<high, digits...> { 

यह क्या है? एक टेम्पलेट विशेषज्ञता जो विशेषज्ञ नहीं है?

और मैं उलझन में हूँ क्यों एक struct घोषणा

struct conv2bin<high> { 
    static_assert(high == '0' || high == '1', "no bin num!"); 
    static int const value = (high - '0'); 
}; 

की तरह इसके अंदर कोड लाइनों है करता है ..

+0

हां, गलती के लिए खेद है – Paul

+2

इन लिंक पर एक नज़र डालें। उन्हें सबकुछ समझा जाना चाहिए। - [वैराडिक टेम्पलेट्स] (http://www.cplusplus.com/articles/EhvU7k9E/) - [उपयोगकर्ता-परिभाषित साहित्य] (http://en.cppreference.com/w/cpp/language/user_literal) - [स्टेटिक अभिकथन] (http://en.cppreference.com/w/cpp/language/static_assert) –

उत्तर

22

आपका कोड तीन नए सी ++ 11 सुविधाओं दिखाता है: variadic टेम्पलेट्स, उपयोगकर्ता परिभाषित अक्षर और स्थिर दावे

सामान्य वैरिएडिक क्लास टेम्पलेट शून्य या अधिक तर्क, विशेष संस्करण एक या अधिक, और बिल्कुल एक निर्दिष्ट करता है।

// digits can be the empty set, so 0 or more arguments 
template<char... digits> 
struct conv2bin; 

// digits can be the empty set, so 1 or more arguments 
template<char high, char... digits> 
struct conv2bin<high, digits...> 

// fully specialized for 1 argument 
template<char high> 
struct conv2bin<high> 

variadic टेम्प्लेट के पूरे वाक्य रचना थोड़ा विचित्र है, Wikipedia उस पर एक सभ्य लेख है। यह विशेष रूप से किसी अन्य सी ++ 11 सुविधा के लिए उपयोगी है: फ़ंक्शन तर्कों की एक भिन्न संख्या के सही अग्रेषण।

विदेशी दिखने वाले int operator "" _b() उपयोगकर्ता द्वारा परिभाषित शाब्दिक परिभाषित करता है, जो आपके स्वयं के इकाइयों को आपके प्रकार और अभिव्यक्ति में जोड़ने का एक तरीका है। इसका मतलब यह है कि _b के बाद पूर्णांक एक निश्चित "इकाई" के साथ टैग किए जाते हैं। अधिक जानकारी के लिए यह question देखें। भविष्य में मंगल ग्रह के लैंडर दुर्घटनाओं से बचने के लिए एक व्यावहारिक लाभ होगा (जहां एसआई और शाही इकाइयों को उनके लैंडिंग सॉफ़्टवेयर में मिश्रित किया जा रहा था, संकलक इसे निदान करने में सक्षम होने के बिना)।

static_assert ठीक वही करता है जो आपको लगता है: यह स्थिर रूप से इसकी स्थिति का दावा करता है, यानी संकलन-समय पर। जब दावा विफल रहता है, संकलन रोक दिया जाता है। जितनी जल्दी हो सके त्रुटियों का पता लगाने का यह एक शानदार तरीका है।

अद्यतन

variadic टेम्पलेट्स के विशेषज्ञता बहुत ही आश्चर्य की आप बहस केआंशिक रूप से अतिव्यापी पर्वतमाला है जब हो सकता है: मामले में शून्य या अधिक तर्क संस्करण केवल अपने उदाहरण में एक खाली सूची के अनुरूप होगा (क्या तुम करोगी इसके लिए एक परिभाषा प्रदान की है)।

#include <iostream> 

template<int... Args> 
struct Test 
{ 
    enum { value = 0 }; 
}; 

template<int I, int... Args> 
struct Test<I, Args...> 
{ 
    enum { value = 2 }; 
}; 

template<int I> 
struct Test<I> 
{ 
    enum { value = 1 }; 
}; 

int main() 
{ 
    std::cout << Test<>::value << "\n";  // matches zero or more version 
    std::cout << Test<0>::value << "\n"; // matches single argument version 
    std::cout << Test<0, 0>::value << "\n"; // matches one or more version, not the zero or more one! 
} 

आउटपुट LiveWorkSpace पर आउटपुट।

यह निश्चित रूप से आंशिक टेम्पलेट विशेषज्ञता के लिए सामान्य नियम का एक उदाहरण है जो बताता है कि सबसे विशिष्ट संस्करण का चयन किया जाएगा (एक या अधिक शून्य या अधिक से अधिक विशिष्ट है, क्योंकि उत्तरार्द्ध कर सकते हैं हमेशा इस्तेमाल किया जा सकता है जहां पूर्व कर सकते हैं, लेकिन इसके विपरीत नहीं)। लेकिन क्योंकि विविधता वाले टेम्पलेट अक्सर एक दूसरे से अलग "स्पष्ट रूप से" अलग नहीं होते हैं, इसलिए आपको अपने आंशिक विशेषज्ञता के साथ अतिरिक्त सावधान रहना चाहिए।

1
template<char... digits> 
struct conv2bin; 

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

template<char high, char... digits> 
struct conv2bin<high, digits...> { 
    static_assert(high == '0' || high == '1', "no bin num!"); 
    static int const value = (high - '0') * (1 << sizeof...(digits)) + 
          conv2bin<digits...>::value; 
}; 

यह एक आंशिक विशेषज्ञता है, जहां एक टेम्पलेट मान सेट किया गया है। बाकी को सिर्फ टेम्पलेट प्रकार के "निचले स्तर स्तर" पर अग्रेषित किया जाता है। यह टेम्पलेट संरचना पूरी तरह परिभाषित है, और इसमें एक int सदस्य चर शामिल है, जो मान 'उच्च' मान और अगले टेम्पलेट पर निर्भर करता है।

template<char high> 
struct conv2bin<high> { 
    static_assert(high == '0' || high == '1', "no bin num!"); 
    static int const value = (high - '0'); 
}; 

फिर से आंशिक टेम्पलेट विशेषज्ञता, मान को परिभाषित करते समय टेम्पलेट पैरामीटर में इसकी सूची में केवल एक पैरामीटर होता है।

तो, कुल मिलाकर यह template meta-programming विविधता टेम्पलेट का उपयोग कर रहा है।


वैल्यू टेम्पलेट वैरिएबल ले सकते हैं मानों को सीमित करने के लिए स्थिर आवेषण हैं।