2012-05-03 22 views
11

में वैरिएबल टेम्पलेट्स को संभालना मैंने हाल ही में सी ++ 11 का उपयोग करना शुरू कर दिया है, और मैंने विविध टेम्पलेट्स के बारे में एक ट्यूटोरियल में पढ़ा है। मैं समझ गया है कि हम इससी ++ 11

// example class that uses variadic template 
template<typename ...Args> struct mtuple; 

की तरह एक variadic टेम्पलेट परिभाषित कर सकते हैं लेकिन मैं mtuple वर्ग के टेम्पलेट तर्क कैसे संभाल कर सकते हैं (अर्थात कैसे get<int>(mtuple_obj) देखो की तरह चाहेगा?)?

+4

वैराडिक टेम्पलेट जादू वास्तव में जादुई है, आपको इसके साथ प्रयोग करना होगा, साथ ही साथ देखने के लिए कई अलग-अलग कोड नमूने देखेंगे कि वहां और क्यों चल रहा है। [यहां मेरा ट्यूपल क्लास लिखने का मेरा प्रयास है (हालांकि 'टाई()' डी) पर नज़र डालें] (https://github.com/griwes/LibRose/blob/master/librosec%2B%2B/tuple .hxx), ऐसे कोड नमूने में से एक के रूप में, यहां बहुत से लोग हैं, एसओ - ब्राउज़ करें [टैग: वैरिएडिक-टेम्पलेट्स] और उन्हें समझने की कोशिश करें। – Griwes

+1

कुछ दिलचस्प संबंधित प्रश्न: http://stackoverflow.com/a/7868427/170521 और http://stackoverflow.com/q/7870498/170521 – lurscher

उत्तर

4

get<1>(t) ऐसा लगता है कि mtuple के कार्यान्वयन पर निर्भर करेगा। एक सामान्य कार्यान्वयन को प्रत्येक प्रकार के तर्क से पुन: प्राप्त होता है, इसलिए mtuple<A,B,C>TupleHead<A> (जिसमें A प्रकार का सदस्य है) से विरासत प्राप्त होती है और TupleTail<B,C> से भी प्राप्त होती है। TupleTail<B,C>TupleHead<B> से विरासत (जिसमें B प्रकार का सदस्य है) और TupleTail<C>TupleHead<C> से TupleTail<C> inherits

अब, आप प्रत्येक आधार वर्ग भी एक पूर्णांक पैरामीटर देते हैं (जो प्रकार C के एक सदस्य है।): TupleHead<0,A> से

mtuple<A,B,C> संभालते हैं और TupleHead<1,B> से TupleTail<1,B,C>

TupleTail<1,B,C> संभालते हैं और TupleTail<2,C>

TupleTail<2,C>TupleHead<2,C>

से विरासत

अब get<1> लिखने के लिए अपेक्षाकृत सरल है, क्योंकि mtuple में TupleHead<1,B> का एक अद्वितीय आधार वर्ग है जो एक ऊपरी भाग से प्राप्त किया जा सकता है, फिर उस बेस क्लास के B सदस्य को वापस करें।

[संपादित करें: get<1>(m)TupleHead<1,T> आधार पाने के लिए प्रकार B कि सूचकांक 1 के साथ टपल तत्व से मेल खाती है पता करने के लिए की जरूरत है, उसके लिए आपको std::tuple_element की तरह कुछ जो भी पुनरावर्ती वंशानुगत पदानुक्रम ऊपर वर्णित पर निर्भर करता है और आंशिक विशेषज्ञता का उपयोग करता है का उपयोग करें सूचकांक 1 के साथ वर्ग, तो वह आंशिक विशेषज्ञता है, जो मेरे उदाहरण में B देता में पैरामीटर T निर्धारित करता है।]

variadic टेम्पलेट्स के साथ इस्तेमाल किया तकनीकों में से कई इस तरह के टेम्पलेट के पहले तत्व पर काम के रूप में कार्यात्मक प्रोग्रामिंग तकनीक, कर रहे हैं पैरामीटर पैक, तब तक पैक के शेष पर एक ही चीज़ कर रहे हैं, जब तक कि आपके पास पीआर न हो सभी तत्वों को उजागर किया।इसके आकार को गिनने के अलावा आप सीधे टेम्पलेट पैरामीटर पैक के साथ कई चीजें नहीं कर सकते हैं (sizeof... के साथ) या उसके साथ एक और टेम्पलेट तत्काल करें, इसलिए सामान्य दृष्टिकोण दूसरे टेम्पलेट को चालू करना है जो पैक Args को ArgHead, ArgsTail... में विभाजित करता है और सिर को संसाधित करता है , फिर ArgsTail

4

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

template<typename T, typename... Args> 
void print_values(const char *s, T value, Args... args) 
{ 
    while (*s) { 
     if (*s == '%' && *(++s) != '%') { 
      std::cout << value; 
      ++s; 
      print_values(s, args...); 
      return; 
     } 
     cout << *(s++); 
    } 
} 

तो, अगर मैं print_values("%d %d %d", 1, 2, 3) फोन मैं इस प्रत्यावर्तन पेड़ मिलती है:: यहाँ एक उदाहरण है

print_values("%d %d %d", 1, 2, 3) // value -> 1, args... -> 2,3 
print_values("%d %d", 2, 3) // value -> 2, args... -> 3 
print_values("%d", 3) // value -> 3, args... -> NULL 
print_values("") // value -> NULL, args... -> NULL 

मैं रिकर्सिवली print_values() फोन भी जब * रों == 0 अतिरिक्त तर्क

पता लगाने के लिए स्रोत: http://en.wikipedia.org/wiki/Variadic_templates