2015-02-07 5 views
7

के रूप में नहीं मिला है, मैं std::ostream और किसी भी इटेबल प्रकार के लिए सामान्य operator<< बनाने की कोशिश कर रहा हूं।सी ++ टेम्पलेट ऑपरेटर मैच

इस कोड है:

template <class T,template<class> class Iterable> inline std::ostream& operator<<(std::ostream& s,const Iterable<T>& iter){ 
    s << "[ "; 
    bool first=false; 
    for(T& e : iter){ 
     if(first){ 
      first=false; 
      s << e; 
     }else{ 
      s << ", " << e; 
     } 
    } 
    s << " ]"; 
    return s; 
} 

दुर्भाग्य से मेरी ऑपरेटर एक vector<uint> के लिए एक मैच के रूप में नहीं पाया जाता है और संकलक operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x) साथ मिलान करने के लिए प्रयास करता है।

कोई विचार है कि मैं ओवरलोड को कैसे पहचान सकता हूं?

+1

एक और समस्या यह है कि आप एक गैर-कॉन्स 'टी '' का उपयोग कर 'const' कंटेनर पर फिर से प्रयास करने का प्रयास करते हैं। इसके बजाय 'टी &&' या 'टी कॉन्स्ट 'का उपयोग करें। –

+3

इसके अलावा आपको पहले –

उत्तर

4

आपकी समस्या का सीधा समाधान है कि vectorदो प्रकार, नहीं एक पर एक टेम्पलेट है, तो आप लिखना चाहते हैं होता है:

template <typename... T, template <typename... > class Iterable> 
inline std::ostream& operator<<(std::ostream& os, const Iterable<T...>& iter) 
{ 
    s << "[ "; 
    bool first = true; // not false 
    for (const auto& e : iter) { 
     // rest as before 
    } 
    return s << " ]"; 
} 

काम करता है यही कारण है, लेकिन एक छोटे से नाकाफी है - के बाद से कुछ चीजें जो टेम्पलेट्स हैं, वे पुनरावृत्त नहीं हैं और कुछ चीजें जो टेम्पलेट नहीं हैं। इसके अलावा, हमें वास्तव में हमारे समाधान में Iterable या T की आवश्यकता नहीं है। तो कैसे के बारे में हम कुछ है कि किसी भी रेंज लेता लिखने - जहाँ हम कुछ है कि एक begin() और end() के रूप में सीमा निर्धारित करें:

template <typename Range> 
auto operator<<(std::ostream& s, const Range& range) 
-> decltype(void(range.begin()), void(range.end()), s) 
{ 
    // as above, except our container is now named 'range' 
} 

अगर ऐसा है भी सामान्य है, तो आप कर सकते हैं:

template <typename T> struct is_range : std::false_type; 
template <typename T, typename A> 
struct is_range<std::vector<T,A>> : std::true_type; 
// etc. 

template <typename Range> 
typename std::enable_if< 
    is_range<Range>::value, 
    std::ostream& 
>::type 
operator<<(std::ostream& s, const Range& range)  
+1

धन्यवाद के लिए प्रारंभ करना चाहिए। दुर्भाग्य से यह मेरे लिए काम नहीं करता है, शायद ऑपरेटर बहुत सामान्य है। बीमार 'ऑपरेटर के लिए अस्पष्ट अधिभार' जैसी कई त्रुटियां प्राप्त करें << '(ऑपरेंड प्रकार' std :: stringstream {aka std :: basic_stringstream } 'और' std :: string {aka std :: basic_string } '' क्योंकि 'string' शुरू हो गया है() और अंत() – tly

+1

आप केवल 'टाइपनाम std :: enable_if :: मान, std :: ostream &> :: type' लिख सकते हैं और' is_container 'के लिए एक प्रकार का विशेषता प्रदान कर सकते हैं जो आप चाहते हैं वह करता है। – Barry

+0

@ बैरी मैं 'रेंज' नाम का उपयोग करता हूं, भले ही यह मानकीकृत नहीं है। हमारे पास लूप के लिए श्रेणी-सीमा से आवश्यकताएं हैं, हालांकि, और कुछ इसी तरह अनुकरण कर सकते हैं मुफ्त 'स्टार्ट' और 'एंड' फ़ंक्शंस (प्लस लुकअप ट्रिक्स) का उपयोग करके। – dyp

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