2017-05-24 32 views
6

निम्नलिखित कोड पर विचार करें, जी ++ 7.0.1 के साथ संकलित उपयोग करने के लिए (-std = C++ 17):std :: टपल के नक्शे टपल और क़ायम करना

#include <map> 
#include <tuple> 

int main() 
{ 
    // Create an alias for a tuple of three ints 
    using ThreeTuple=std::tuple<int,int,int>; 
    // Create an alias for a map of tuple to tuple (of three ints) 
    using MapThreeTupleToThreeTuple=std::map<ThreeTuple,ThreeTuple>; 

    MapThreeTupleToThreeTuple m; 

    // The following does NOT compile 
    m.emplace({1,2,3},{4,5,6}); 

    // ..., and neither does this 
    m.emplace(std::piecewise_construct,{1,2,3},{4,5,6}); 
} 

मैं सोचा होगा कि initializer_list तर्क map::emplace() तक पर्याप्त होगा और इसके परिणामस्वरूप निर्दिष्ट मूल्य के रूप में मूल्य संघ को टुपल करने के लिए टुपल कुंजी को सम्मिलित किया जाएगा। जाहिर है, संकलक असहमत है।

स्पष्ट रूप से एक टपल बनाने बेशक

(यानी, के बजाय ThreeTuple{1,2,3} सिर्फ {1,2,3}) और गुजर कि स्वचालित रूप से टपल कंस्ट्रक्टर्स करने के लिए उन्हें आगे हैं जो map::emplace() समस्या का हल, लेकिन क्यों प्रारंभकर्ता सूचियों map::emplace() को सीधे पारित नहीं किया जा सकता है ?

+2

आरंभकर्ता सूचियों में कोई प्रकार नहीं है। 'emplace' टाइप कटौती पर निर्भर करता है। आप एक टाइपलेस चीज़ के लिए एक प्रकार को कम नहीं कर सकते हैं। – NathanOliver

+0

आपको इस मुद्दे के बारे में सी ++ 17 में क्या लगता है? – Walter

+0

@ वाल्टर, मेरा मतलब यह नहीं था कि मैं एक नई सी ++ 17 सुविधा का उपयोग कर रहा हूं, बस मैं सी ++ 17 संगतता स्तर का उपयोग कर रहा था। –

उत्तर

5

लेकिन क्यों प्रारंभकर्ता सूचियों map::emplace()

को सीधे पारित नहीं किया जा सकता है प्रारंभकर्ता सूचियों भाव नहीं हैं और इसलिए वे प्रकार नहीं है। emplace() के लिए हस्ताक्षर बस है:

template< class... Args > 
std::pair<iterator,bool> emplace(Args&&... args); 

और आप {1,2,3} से एक प्रकार अनुमान नहीं कर सकते। आप सी ++ 11 में नहीं हो सकते थे और आप अभी भी सी ++ 1z में नहीं हो सकते हैं। इस नियम का एकमात्र अपवाद यह है कि टेम्पलेट पैरामीटर std::initializer_list<T> के रूप में है जहां T एक टेम्पलेट पैरामीटर है।

आदेश में m.emplace({1,2,3},{4,5,6}); के लिए काम करने के लिए, आप की तरह एक हस्ताक्षर आवश्यकता होगी:

std::pair<iterator,bool> emplace(key_type&&, mapped_type&&); 
+0

'std :: piecewise_construct' के साथ संस्करण के बारे में क्या? एक ही समस्या है? –

+0

@ माइकलगोल्डशेटिन हाँ। यह अभी भी एक 'emplace()' फ़ंक्शन टेम्पलेट है। – Barry

+2

@MichaelGoldshteyn ध्यान दें कि 'प्रारंभकर्ता_सूची' हैं और * प्रारंभकर्ता सूची * हैं। एक * प्रारंभकर्ता_सूची' को * प्रारंभकर्ता सूची * से बनाया जा सकता है क्योंकि यह जानता है कि प्रकार क्या होना चाहिए। एक सादा टेम्पलेट प्रकार ऐसा नहीं करता है। – NathanOliver

5

AFAIK, इस संदर्भ में सी ++ 17 बात में कोई बदलाव नहीं। जैसा कि नेथनऑलिवर और बैरी द्वारा समझाया गया है, {1,2,3} किसी भी प्रकार के लिए नहीं लिया जा सकता है और इसलिए टेम्पलेट तर्क के खिलाफ मिलान नहीं किया जा सकता है। तुम्हें पता है, यानी

m.emplace(std::piecewise_construct, 
      std::forward_as_tuple(1,2,3), 
      std::forward_as_tuple(4,5,6)); 

जो निर्माता

template<typename T1, typename T2> 
template<typename... Args1, typename... Args2 > 
std::pair<T1,T2>::pair(std::piecewise_construct_t, 
         std::tuple<Args1...>, std::tuple<Args2...>); 

कॉल इस विशेष मामले में ThreeTuple रूप निगम्य प्रकार के निर्माता के लिए तर्क प्रदान करनी चाहिए, तुम भी std::piecewise_construct

m.emplace(std::forward_as_tuple(1,2,3), 
      std::forward_as_tuple(4,5,6)); 
छोड़ सकते हैं

या (सी ++ 17 में निकोल द्वारा एक टिप्पणी में इंगित किया गया है)

m.emplace(std::tuple(1,2,3), std::tuple(4,5,6)); 

जो

m.emplace(ThreeTuple(1,2,3), ThreeTuple(4,5,6)); 

के बराबर हैं और निर्माता फोन

template<typename T1, typename T2> 
std::pair<T1,T2>::pair(const&T1, const&T2); 

भी ध्यान रखें कि AFAIK आप std::initializer_list<int> स्पष्ट रूप से उपयोग कर इस काम के नहीं मिल सकता है। कारण यह है कि pair<ThreeTuple,ThreeTuple> (आपके मानचित्र के value_type) के लिए उपयुक्त कन्स्ट्रक्टर नहीं है।

+0

एक कार्य उदाहरण दिखाने के लिए +1 है इसे ठीक से कैसे करें। –

+0

एफवाईआई: चूंकि ओपी सी ++ 17 का उपयोग कर रहा है, इसलिए आप टेम्पलेट क्लास कटौती का भी उपयोग कर सकते हैं और इसलिए बस 'std :: tuple (1, 2, 3)' का उपयोग करें। मान लें कि कंपाइलर इसका समर्थन करता है और मानक पुस्तकालय इसे ठीक से लागू करता है। –

+0

@ निकोलबोलस सही है, लेकिन यह लगभग 'थ्रीप्पल (1,2,3) 'जैसा ही है, जिसे ओपी ने उल्लेख किया है। वैसे भी, मैंने जवाब बदल दिया। – Walter

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