2012-11-26 33 views
8

तो मुझे लगता है कि एक मानक कंटेनर लपेटता एक टेम्पलेट है, यह मैं यथोचित आसानी से initializer_list निर्माता प्रतिनिधि कर सकते हैं लगता है , उदाहरण के लिए।वैकल्पिक रूप से टेम्पलेट्स के लिए initializer_list निर्माण का समर्थन शायद लपेटकर कंटेनर

int main(int argc, char* argv[]) { 

    holder<std::vector<int>> y{1,2,3}; 
    return EXIT_SUCCESS; 
} 

लेकिन यह बहुत स्पष्ट रूप से 'int', या किसी भी अन्य प्रकार है कि एक नेस्टेड VALUE_TYPE typedef नहीं है के रूप में टी के लिए काम नहीं करता। इसलिए, मैं कुछ प्रकार की enable_if या इसी तरह की चाल का उपयोग करना चाहता हूं ताकि प्रारंभकर्ताइज़र_लिस्ट कन्स्ट्रक्टर को उत्सर्जित न किया जाए जब तक कि टी दोनों नेस्टेड वैल्यू टाइप टाइप टाइप नहीं किया जाता है, और std :: startizer_list से रचनात्मक है।

मैं निम्नलिखित की कोशिश की, लेकिन यह अभी भी काम नहीं करता, क्योंकि संकलक (बजना मेरे मामले में ++ 3.1), अभी भी अमान्य टी :: VALUE_TYPE जब टी पूर्णांक है से अधिक यात्राएं:

holder(typename std::enable_if<std::is_constructible<T, std::initializer_list<typename T::value_type>>::value, std::initializer_list<typename T::value_type>>::type values) 
    : t_(values) {} 

कोई अवधारणा को व्यक्त करने के बारे में विचार "टी पर इस टेम्पलेट को टी के वैल्यू_ टाइप पर प्रारंभिक सूची कन्स्ट्रक्टर पर दें, अगर केवल तभी टी के पास value_type टाइपपीफ है और T :: value_type की प्रारंभकर्ता_सूची से रचनात्मक है"।

+0

'initializer_list' सही मान द्वारा पारित, या यह कुछ संदर्भ प्रकार के आधार पर पारित किया जाना चाहिए है? ('&&'?) –

+0

@ मार्टिनबा: मूल्य से गुजरना सही है (और अनुशंसित) 'std :: startizer_list' के लिए। –

+0

एक 'startizer_list' में केवल एक पॉइंटर और आकार होता है, इसलिए इसे मूल्य से पास करना ठीक है। डेटा की प्रतिलिपि नहीं बनाई गई है। –

उत्तर

4

SFINAE केवल टेम्पलेट पैरामीटर सबसेंशन पर काम करता है (इसलिए SFINAE में एस)। निम्नलिखित काम करता है:

template<typename T> 
struct holder { 
    T t_; 

    holder() : 
     t_() {} 

    template<typename U = T> 
    holder(typename std::enable_if<std::is_constructible<U, std::initializer_list<typename U::value_type>>::value, 
    std::initializer_list<typename U::value_type>>::type values) 
    : t_(values) {} 

}; 

आप किसी टेम्पलेट समारोह है, तो पूरी कक्षा प्रकार int (अपने उदाहरण में) के लिए instantiated किया जाएगा, एक संकलक त्रुटि के लिए अग्रणी उपयोग नहीं किया है।

ध्यान दें कि अगर आप एक अतिरिक्त टेम्पलेट पैरामीटर का उपयोग किया फ़ंक्शन हस्ताक्षर अच्छे बना सकता है:

template<typename U = T, class = typename std::enable_if<std::is_constructible<U, std::initializer_list<typename U::value_type>>::value, bool>::type> 
    holder(std::initializer_list<typename U::value_type> values) 
    : t_(values) {} 
+0

दिलचस्प है, लेकिन यह काफी काम नहीं करता है। मेरे मूल संस्करण 'धारक > y = {1, 2, 3} 'सही ढंग से काम करता है, लेकिन कम से कम मेरे कंपाइलर के साथ यह आपके संशोधित कन्स्ट्रक्टर हस्ताक्षर के साथ काम नहीं करता है। यह शिकायत करता है कि 'उम्मीदवार कन्स्ट्रक्टर टेम्पलेट व्यवहार्य नहीं है: 1 तर्क की आवश्यकता है, लेकिन 3 प्रदान किए गए थे' – acm

+2

क्या आप enable_if को छोड़ नहीं सकते थे और बस 'टेम्पलेट <टाइपनाम यू = टी> धारक (std :: startizer_list मूल्य) '? –

+0

@VaughnCato जो बेहतर काम करने लगता है। – acm