5

एक महान लेख True Story: Efficient Packing के पढ़ने के बाद है मैं व्यायाम के रूप में टपल को लागू करने की कोशिश की अपने आप से:कार्य करने के लिए कॉल अस्पष्ट जब अप्रासंगिक प्रकार उपनाम के रूप में परिभाषित किया गया

#include <type_traits> 
#include <utility> 
#include <functional> 

template< std::size_t I, typename T > 
struct tuple_leaf { T value; }; 

template< std::size_t I, typename T > 
T & get(tuple_leaf< I, T > & leaf) 
{ return leaf.value; } 

template< typename Is, typename ...Ts > 
struct tuple_base; 

template< std::size_t ...Is, typename ...Ts > 
struct tuple_base< std::index_sequence<Is...>, Ts... > 
    : tuple_leaf< Is, Ts >... 
{ 
    using tuple_base_t = tuple_base; 
    template< typename ...Args, typename = std::enable_if_t< (sizeof...(Ts) == sizeof...(Args)) > > 
    tuple_base(Args &&... args) 
     : tuple_leaf< Is, Ts >{std::forward<Args>(args)}... 
    { ; } 
}; 

#if 0 
template< typename ...Ts > 
struct tuple 
    : tuple_base< std::index_sequence_for<Ts...>, Ts... > 
{ 
    using tuple_base_t = typename tuple::tuple_base_t; 
    using tuple_base_t::tuple_base_t; 
    using tuple_base_t::operator = ; 
}; 
#else 
// terse 
template< typename ...Ts > 
using tuple = tuple_base< std::index_sequence_for<Ts...>, Ts... >; 
#endif 

template< typename ...Args > 
tuple< Args &&... > 
forward_as_tuple(Args &&... args) 
{ return {std::forward<Args>(args)...}; } 

#include <tuple> 

int 
main() 
{ 
    tuple<int> t(1); 
    auto f = forward_as_tuple(t); 
    (void)f; 
    return 0; 
} 

Live example

मैं करने का फैसला forward_as_tuple के कार्यान्वयन के बाद tupleवर्ग टेम्पलेट से उपनाम टेम्पलेट अपने बेस क्लास टेम्पलेट के प्रकार की परिभाषा को बदलें, क्योंकि मुझे कक्षा tuple में विभाजित करने की आवश्यकता है और इसके कार्यान्वयन वर्ग tuple_base भिन्नता टेम्पलेट प्रकार पैरामीटर पैक के लिए std::index_sequence_for है - उपनाम टेम्पलेट इस उद्देश्य के लिए बिल्कुल उपयुक्त उपकरण है। कर रही है कि मैं एक त्रुटि (#if 0 मामले) प्राप्त करने के बाद:

error: call to 'forward_as_tuple' is ambiguous

यह मेरे लिए अजीब लग रहा है, क्योंकि उर्फ ​​टेम्पलेट कुछ नहीं करता है और दूसरी ओर forward_as_tuple एक ही नाम स्थान से प्रकार के लिए कहा जाता है पर - मुझे उम्मीद थी कि एडीएल को निश्चित रूप से उपरोक्त मामले के लिए काम करना चाहिए।

कोड के संस्करण #if 1 और #if 0 के बीच अंतर को कैसे समझाया जाए?

+0

'std :: index_sequence_for' फ़ंक्शन कॉल के तर्क के प्रकार का एक प्रकार का टेम्पलेट तर्क बन जाता है, इसलिए एडीएल द्वारा' std' की जांच की जाती है। Btw। यदि आप 'tuple ' सीधे –

+0

@PiotrSkotnicki सूक्ष्म पल का उपयोग करते हैं तो आपको वही त्रुटि मिल जाएगी। मैं हमेशा यह ध्यान में रखता हूं कि एडीएल केवल फ़ंक्शन तर्क प्रकारों के लिए है, लेकिन टेम्पलेट पैरामीटर के लिए भी है। – Orient

+0

@PiotrSkotnicki 'tuple_base , int>>, tuple_base , int>> 'फ़ंक्शन तर्क है। 'std :: index_sequence_for' गहरा अंदर है। अर्थात। यह शीर्ष टेम्पलेट नाम नहीं है। फर्क पड़ता है क्या? – Orient

उत्तर

3

एडल पास किए गए प्रकार में लुकअप का कारण बनता है, और प्रकार के टेम्पलेट तर्क पास हुए।

ट्यूपल गैर-उपनामों में एडीएल देखने के लिए स्थानों के रूप में इसके प्रकार और स्वयं होते हैं।

टुपल उपनाम मामले में इसकी टेम्पलेट तर्क सूची में std::index_sequence है। यह आपके forward_as_tuple के अतिरिक्त, std::forward_as_tuple पर विचार किया जा सकता है। वे समान रूप से अच्छे मैच हैं, और अस्पष्टता होती है।

जैसा कि @Piotr टिप्पणियों में ऊपर उल्लेख किया गया है, tuple<std::string> गैर-उपनाम मामले में भी इस समस्या को प्रदर्शित करता है।

संबंधित मुद्दे

 संबंधित मुद्दे