2012-09-15 24 views
20

मैं gcc4.7 साथ निम्नलिखित के टुकड़े को संकलित करने की कोशिश कीटपल वेक्टर और initializer_list

vector<pair<int,char> > vp = {{1,'a'},{2,'b'}}; 
//For pair vector, it works like a charm. 

vector<tuple<int,double,char> > vt = {{1,0.1,'a'},{2,4.2,'b'}}; 

हालांकि, tuples के वेक्टर के लिए, संकलक शिकायत:

त्रुटि: 'के लिए std :: टपल परिवर्तित 'प्रारंभकर्ता सूची से स्पष्ट कन्स्ट्रक्टर' constexpr std :: tuple <> :: tuple (_UElements & & ...) [_UElements = {int, double, char} के साथ; = शून्य; _Elements = {int, double, char}] '

कंपाइलर द्वारा छोड़ा गया त्रुटि जानकारी मेरे लिए कुल गड़बड़ है, और मुझे नहीं पता कि टुपल के निर्माता कैसे कार्यान्वित किए गए थे, फिर भी मुझे पता है कि वे पूरी तरह से ठीक हैं समान प्रारंभिकरण के साथ (जैसे: tuple<int,float,char>{1,2.2,'X'}), इसलिए, मुझे आश्चर्य है कि मुझे जिस समस्या का सामना करना पड़ा वह केवल कंपाइलर का एक TODO है या यह C++ 11 मानक द्वारा परिभाषित कुछ है।

किसी भी प्रतिक्रिया की सराहना की जाएगी!

उत्तर

25

आप tuple निर्माता पर एक reference page जाँच हैं, तो आप यह है कि यह std::initializer_list जो वर्ग प्रारंभकर्ता सूचियों को स्वीकार करने के लिए सक्षम होने के लिए के लिए आवश्यक है नहीं ले करता है देखेंगे।

आप std::make_tuple साथ वेक्टर प्रारंभ:

vector<tuple<int,double,char>> vt = 
    { std::make_tuple(1,0.1,'a'), std::make_tuple(2,4.2,'b') }; 
+0

माफ़ कीजिये! मैंने एक टाइपो बनाया, फिर से काम किया, लेकिन अभी भी काम नहीं करेगा! – Need4Steed

+0

@ Need4Steed मेरा उत्तर अपडेट किया गया। –

+0

मैंने make_tuple की कोशिश की, यह ठीक काम करता है, लेकिन यह मेरे लिए असंगत लगता है अगर यह जोड़े के साथ ठीक है लेकिन tuples के साथ नहीं जाना है। – Need4Steed

5

प्रासंगिक std::tuple कंस्ट्रक्टर्स explicit हैं। इसका अर्थ यह है कि आप जो करना चाहते हैं वह संभव नहीं है, क्योंकि जिस वाक्यविन्यास का आप उपयोग करना चाहते हैं उसे कॉपी प्रारंभिकरण के संदर्भ में परिभाषित किया गया है (जो explicit कन्स्ट्रक्टर को कॉल करने से मना कर देता है)। इसके विपरीत, std::tuple<int, float, char> { 1, 2.2, 'X' } प्रत्यक्ष प्रारंभिक उपयोग करता है। std::pair में गैर-explicit केवल रचनाकार हैं।

या तो प्रत्यक्ष-प्रारंभिकरण या मानक ट्यूपल फैक्ट्री फ़ंक्शन में से एक का उपयोग करें (उदा। std::make_tuple)।

0

यह वास्तव में करने योग्य है, सी ++ 11 सुविधाओं के साथ।

हां प्रारंभकर्ता_सूची चाहता है कि उसका सभी तत्व एक ही प्रकार का हो। चाल यह है कि हम एक रैपर वर्ग बना सकते हैं जो static_cast हो सकता है जो हम चाहते हैं। इस लक्ष्य को हासिल करने के लिए आसान है:

template <typename... tlist> 
class MultiTypeWrapper { 
}; 

template <typename H> 
class MultiTypeWrapper<H> { 
public: 
    MultiTypeWrapper() {} 

    MultiTypeWrapper(const H &value) : value_(value) {} 

    operator H() const { 
    return value_; 
    } 
private: 
    H value_; 
}; 

template <typename H, typename... T> 
class MultiTypeWrapper<H, T...> 
    : public MultiTypeWrapper<T...> { 

public: 
    MultiTypeWrapper() {} 

    MultiTypeWrapper(const H &value) : value_(value) {} 

    // If the current constructor does not match the type, pass to its ancestor. 
    template <typename C> 
    MultiTypeWrapper(const C &value) : MultiTypeWrapper<T...>(value) {} 

    operator H() const { 
    return value_; 
    } 
private: 
    H value_; 
}; 
अंतर्निहित रूपांतरण कंस्ट्रक्टर्स साथ

, हम {4 1,2.5, 'सी',} एक initializer_list (या वेक्टर, जो परोक्ष initializer_list धर्मान्तरित) प्रकार की करने के लिए की तरह कुछ पारित कर सकते हैं MultiTypeWrapper। इसका मतलब यह है कि हम नीचे की तरह एक समारोह तर्क के रूप में इस तरह के intializer_list स्वीकार करने के लिए नहीं लिख सकता:

template <typename... T> 
std::tuple<T...> create_tuple(std::vector<unit_test::MultiTypeWrapper<T...> > init) { 
    .... 
} 

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

template <int ind, typename... T> 
class helper { 
public: 
    static void set_tuple(std::tuple<T...> &t, const std::vector<MultiTypeWrapper<T...> >& v) { 
    std::get<ind>(t) = static_cast<typename std::tuple_element<ind,std::tuple<T...> >::type>(v[ind]); 
    helper<(ind-1),T...>::set_tuple(t,v); 
    } 
}; 



template <typename... T> 
class helper<0, T...> { 
public: 
    static void set_tuple(std::tuple<T...> &t, const std::vector<MultiTypeWrapper<T...> >& v) { 
    std::get<0>(t) = static_cast<typename std::tuple_element<0,std::tuple<T...> >::type>(v[0]); 
    } 
}; 



template <typename... T> 
std::tuple<T...> create_tuple(std::vector<unit_test::MultiTypeWrapper<T...> > init) { 
    std::tuple<T...> res; 
    helper<sizeof...(T)-1, T...>::set_tuple(res, init); 
    return res; 
} 

नोट हम C++ समारोह विशेषज्ञता का समर्थन नहीं करता क्योंकि set_tuple के लिए सहायक वर्ग तैयार करने होंगे।अब हम कोड का परीक्षण करना चाहते हैं:

auto t = create_tuple<int,double,std::string>({1,2.5,std::string("ABC")}); 
printf("%d %.2lf %s\n", std::get<0>(t), std::get<1>(t), std::get<2>(t).c_str()); 

उत्पादन होगा:

1 2.50 ABC 

यह बजना के साथ अपने डेस्कटॉप पर परीक्षण किया जाता है 3.2

आशा है कि मेरी इनपुट में मदद करता है :)

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