2015-12-09 16 views
15

मेरा मतलब है कि std::make_tuple क्यों मौजूद है? मुझे पता है कि ऐसी परिस्थितियां हैं जहां फ़ंक्शन आपके द्वारा टाइप किए जाने वाले वर्णों की मात्रा को कम कर देता है क्योंकि आप टेम्पलेट पैरामीटर से बच सकते हैं। लेकिन क्या यह एकमात्र कारण है? std::tuple क्या विशेष बनाता है कि फ़ंक्शन मौजूद है जबकि अन्य क्लास टेम्पलेट्स में ऐसा फ़ंक्शन नहीं है? क्या यह केवल इसलिए है क्योंकि आप ऐसी स्थितियों में std::tuple अधिक बार उपयोग कर सकते हैं?`std :: make_tuple` का कारण क्या है?

// Avoiding template parameters in definition of variable. 
// Consider that template parameters can be very long sometimes. 
std::tuple<int, double> t(0, 0.0); // without std::make_tuple 
auto t = std::make_tuple(0, 0.0); // with std::make_tuple 

// Avoiding template parameters at construction. 
f(std::tuple<int, double>(0, 0.0)); // without std::make_tuple 
f(std::make_tuple(0, 0.0));   // with std::make_tuple 

लेकिन जैसे ऊपर लिखा है, तो आप कई अन्य वर्ग टेम्पलेट्स के लिए इस तरह एक समारोह नहीं है:


यहां दो उदाहरण हैं जहां std::make_tuple पात्रों की मात्रा को कम कर रहे हैं।

+3

कई समान कार्य हैं, लेकिन सबसे स्पष्ट प्रत्यक्ष तुलना ['std :: make_pair'] है (http://en.cppreference.com/w/cpp/utility/pair/make_pair)। मुझे लगता है कि अंगूठे का नियम यह हो सकता है कि वे मौजूद हों यदि आप इन ऑब्जेक्ट्स को किसी अन्य अभिव्यक्ति के हिस्से के रूप में बनाना चाहते हैं, फ़ंक्शन को कॉल करने के लिए, आदि – BoBTFish

+0

आपको अन्य मेक_ * फ़ंक्शन के लिए कौन सा वर्ग पसंद आएगा? हम पहले से ही make_shared, make_unique, आदि प्राप्त कर रहे हैं –

+1

केवल अंतर ही कटौती प्रकार है। लेकिन कटौती का प्रकार उपयोगी हो सकता है, इसलिए यही कारण है। –

उत्तर

18

क्योंकि आप रचनाकारों के लिए तर्क कटौती का उपयोग नहीं कर सकते हैं। आपको स्पष्ट रूप से std::tuple<int, double>(i,d); लिखना होगा।

यह एक ट्यूपल बनाने और इसे एक-शॉट में किसी अन्य फ़ंक्शन में पास करने के लिए अधिक सुविधाजनक बनाता है।

takes_tuple(make_tuple(i,d)) बनाम takes_tuple(tuple<int,double>(i,d))

i या d परिवर्तनों के प्रकार को बदलने के लिए एक कम जगह, खासकर अगर पुराने और नए प्रकार के बीच संभावित रूपांतरण हो।

यदि यह संभव थे लिखने के लिए std::tuple(i,d);, make_* (शायद) बेमानी होगा।

(मत पूछो यहाँ क्यों इन्हीं कारणों से हो सकता है कि क्यों वाक्य रचना A a(); एक डिफ़ॉल्ट निर्माता आह्वान नहीं होता C++ वाक्य रचना peculiarities कुछ दुखदाई है।।।)

अद्यतन नोट: रूप Daniel ठीक ही नोटिस, सी ++ 17 बढ़ाया जाएगा, ताकि टेम्पलेट तर्क कटौती कन्स्ट्रक्टर के लिए काम करेगी, और ऐसा प्रतिनिधिमंडल अप्रचलित हो जाएगा।

+4

** सी ++ 17 ** के बाद से, ** कक्षा टेम्पलेट कटौती **, यानी, 'std :: tuple t (1, 1.0, 'a') लिखने के लिए संभव होगा;' या 'ऑटो टी = std :: tuple (1, 1.0, 'a'); '। विवरण के लिए, उदाहरण के लिए, [यहां] (http://en.cppreference.com/w/cpp/language/class_template_deduction) देखें। –

+0

उत्तर में अपना अद्यतन नोट शामिल किया गया। इसे कॉल करने के लिए धन्यवाद। – luk32

+0

@ luk32 "और ऐसा प्रतिनिधिमंडल अप्रचलित हो जाएगा" मैं असहमत हूं: 'std :: make_tuple'' x & 'का उपयोग करेगा यदि आप 'std :: ref()' कॉल में कुछ लपेटते हैं, जो अभी भी C++ 17 में उपयोगी होगा , ['std :: tuple'] के लिए कटौती मार्गदर्शिकाएं (http://en.cppreference.com/w/cpp/utility/tuple/deduction_guides) ऐसे मामले को संभालने के लिए प्रतीत नहीं होती हैं। –

7

हम के लिए कारण है कि हम जरूरत make_tuple एक तर्क और प्रस्ताव N3602: Template parameter deduction for constructors में विभिन्न अन्य make_ * उपयोगिताओं जो कहते हैं (जोर मेरा) पा सकते हैं: कंस्ट्रक्टर्स के कार्यों के लिए

इस पत्र का विस्तार का प्रस्ताव टेम्पलेट पैरामीटर कटौती टेम्पलेट कक्षाओं का। समस्या और समाधान का वर्णन करने का सबसे स्पष्ट तरीका कुछ उदाहरणों के साथ है।

मान लीजिए कि हमने निम्नलिखित को परिभाषित किया है।

:

vector<int> vi1 = { 0, 1, 1, 2, 3, 5, 8 }; 
vector<int> vi2; template<class Func> 
    class Foo() { 
     public: Foo(Func f) : func(f) {} 
     void operator()(int i) { os << "Calling with " << i << endl; f(i); } 
     private: 
     Func func; 
    }; 

वर्तमान में, अगर हम टेम्पलेट वर्गों का दृष्टांत करना चाहते हैं, हम के लिए या तो टेम्पलेट पैरामीटर निर्दिष्ट या कार्यों के लिए एक "make_ *" आवरण, का लाभ उठाने टेम्पलेट पैरामीटर कटौती का उपयोग करें, या पूरी तरह से बाज़ी की जरूरत है

pair<int, double> p(2, 4.5); 
auto t = make_tuple(4, 3, 2.5); 
copy_n(vi1, 3, back_inserter(vi2)); // Virtually impossible to pass a lambda to a template class' constructor 
for_each(vi.begin(), vi.end(), Foo<???>([&](int i) { ...})); 

नोट, प्रस्ताव EWG issue 60 के माध्यम से ट्रैक किया जा रहा है।

+0

@black अच्छी तरह से ईडब्ल्यूजी मुद्दा जो मैंने अभी अपने उत्तर में जोड़ा है, कुछ मुद्दों का सुझाव देता है, लेकिन काम को प्रोत्साहित किया गया था। ईडब्ल्यूजी सक्रिय सूची अभी तक कोना से अपडेट नहीं की गई थी, इसलिए शायद यह बदल गया है। –

1

केवल टेम्पलेट तर्क कटौती के लिए। हालांकि, यहां एक (काल्पनिक) उदाहरण है, जहां यह एक लैम्ब्डा प्रयोग करने के लिए आवश्यक है है:

class A 
{ 
public: 
    template<typename F> 
    A(const std::tuple<F> &t) 
    { 
     // e.g. 
     std::get<0>(t)(); 
    } 
}; 

class B : public A 
{ 
public: 
    B(int i) : A(std::make_tuple([&i]{ ++i; })) 
    { 
     // Do something with i 
    } 
}; 

std::tuple<decltype([&i]{ ++i; })>([&i]{ ++i; }) क्योंकि दो लैम्ब्डा भाव विभिन्न प्रकार का उपयोग नहीं किया जा सकता है। std::function जैसे पॉलीमोर्फिक रैपर रनटाइम ओवरहेड जोड़ता है। उपयोगकर्ता द्वारा परिभाषित operator() वाला एक नामित वर्ग ऑपरेटर के शरीर की सामग्री के आधार पर काम करेगा (जिसे B का मित्र भी होना चाहिए)। सी ++ 11 से पहले पुराने दिनों में हमने यही किया था।

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