2013-10-26 2 views
10

के लिए श्रेणी-आधार वाले सभी वर्गों के लिए सुंदर प्रिंट मैं < < ओवरलोडिंग द्वारा लूप समर्थन के लिए श्रेणी-आधार वाले सभी वर्गों के लिए सुंदर प्रिंट लागू करना चाहता हूं। (गलत) कोड इस तरह है।लूप समर्थन

template<class C> ostream& operator<<(ostream& out, const C& v) { 
    for(auto x : v) out<<x<<' '; 
    return out; 
} 

समस्या यहां है कि इस मौजूदा < < अधिक भार का उल्लंघन करेगा है। क्या टेम्पलेट में निर्दिष्ट करने का कोई तरीका है कि सी को लूप के लिए श्रेणी-आधार का समर्थन करना चाहिए?

उत्तर

11

छोरों के लिए के बाद से सीमा आधारित begin(v) और end(v) की आवश्यकता होती है ADL (और std:: एक संबद्ध नाम स्थान में किया जा रहा है) के साथ मान्य होने के लिए, तो आप इस का उपयोग कर सकते हैं:

namespace support_begin_end 
{ 
    // we use a special namespace (above) to 
    // contain the using directive for 'std': 
    using namespace std; 

    // the second parameter is only valid 
    // when begin(C()) and end(C()) are valid 
    template<typename C, 
     typename=decltype(begin(std::declval<C>()),end(std::declval<C>())) 
    > 
    struct impl 
    { 
     using type = void; // only here impl 
    }; 

    // explicitly disable conflicting types here 
    template<> 
    struct impl<std::string>; 
} 

// this uses the above to check for ::type, 
// which only exists if begin/end are valid 
// and there is no specialization to disable it 
// (like in the std::string case) 
template<class C,typename = typename supports_begin_end::impl<C>::type> 
std::ostream& operator<<(std::ostream& out, const C& v) { 
    for(auto x : v) out<<x<<' '; 
    return out; 
} 

Live example

अन्य प्रकार के होते हैं कि हालांकि, श्रेणी आधारित loops के लिए उपयुक्त हैं। पता नहीं है कि आपको उन्हें पहचानने की ज़रूरत है या नहीं।


यहाँ एक अद्यतन live example जो दोनों कंटेनरों/कि begin(v)/end(v) का समर्थन करने वाले v.begin()/v.end() समर्थन प्रकार के साथ ही प्रकार का पता लगाती है।

+0

क्या आप यहां क्या हो रहा है इसका थोड़ा सा समझाएंगे? बहुत अच्छा धन्यवाद होगा! – lfxgroove

+0

@lfxgroove देखें कि अद्यतन उत्तर मदद करता है या नहीं। –

+0

यकीन है, एक ढेर धन्यवाद! – lfxgroove

6

SFINAE: सभी प्रश्नों के उत्तर पर

template<class C> 
auto operator<<(std::ostream& out, const C& v) -> decltype(v.begin(), v.end(), (out)) 
//           or -> decltype(std::begin(v), std::end(v), (out)) 
{ 
    for (auto x : v) 
     out << x << ' '; 
    return out; 
} 
4

एक सामान्य टिप्पणी:

for (auto x : v) 

का उपयोग करते हुए उन्हें मुद्रण से पहले संग्रह से बाहर सभी तत्वों को कॉपी करेंगे, एक बहुत में जिसके परिणामस्वरूप कॉपी कन्स्ट्रक्टर और विनाशक को कॉल का।

for (auto &x : v) 

आपके लूप के रूप में शायद बेहतर हो सकता है।