2011-09-29 26 views
5

नीचे दिए गए नमूना कोड में, यह दिखाता है कि boost :: tuple को पहले टेम्पलेट तर्क से पूरी तरह से बनाया जा सकता है। इसके कारण मैं << ऑपरेटर लिखने में सक्षम नहीं हूं क्योंकि यह संदिग्ध हो जाता है।बढ़ावा देने के लिए `<<` ऑपरेटर कैसे लिखें :: tuple?

मुझे यह भी समझ में नहीं आता कि ostringstream& << float भी संदिग्ध है। इसका कोई अंतर्निहित निर्माण नहीं है। यह अस्पष्ट त्रुटि क्यों देता है?

#include <iostream> 
#include <boost/tuple/tuple.hpp> 
#include <sstream> 
#include <string> 

using namespace std; 

class Myclass 
{ 
}; 

typedef boost::tuple<int,float,Myclass> Mytuple; 

ostringstream& operator<<(ostringstream& os_, Mytuple tuple_) 
{ 
    float f = tuple_.get<1>(); 
    //os_ << (int)tuple_.get<0>(); // Error because int is implicitly converted into Mytuple. WHYY? 
    //os_ << tuple_.get<1>();  // No Clue Why this is ambiguous. 
    //os_ << tuple_.get<2>();  // Error because no matching operator. Fine. 
    return os_; 
} 

int main() 
{ 
    Mytuple t1; 
    t1 = 3;  // Working because int is implicitly converted into Mytuple!! WHY? 
    //t1 = 3.0f; // Error because no matching constructor. Fine. 
    return 0; 
} 

त्रुटि Mesasge:

tupleTest2.C:18: error: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second:

+0

'boost :: tuple' में पहले से ही एक ऑपरेटर <<' है। मैं नहीं देखता कि यह आपके द्वारा प्राप्त त्रुटियों की ओर जाता है लेकिन यह संबंधित हो सकता है। –

+0

इसके अलावा 'boost :: tuple' में tuple तत्वों के 0..n के लिए निर्माता हैं, इसलिए आपके पास एक कन्स्ट्रक्टर' माईटप्ले (int) 'है जो इसे' int' से परिवर्तनीय बनाता है। –

+0

यह मेरे लिए ठीक संकलित करता है - यह जीसीसी 4.5 और जीसीसी 4.7 प्रयोगात्मक के साथ होना चाहिए। आप किस कंपाइलर संस्करण का उपयोग कर रहे हैं? – rodrigo

उत्तर

4

समस्या टपल साथ नहीं है, लेकिन अपने ऑपरेटर के साथ। यह ठीक काम करता है: ostringstream& operator<<(ostringstream& os_, Mytuple tuple_) अनुमति दी है:

ostream& operator<<(ostream& os_, Mytuple tuple_) 
{ 
    os_ << tuple_.get<0>(); // Error because int is implicitly converted into Mytuple. WHYY? 
    os_ << tuple_.get<1>();  // No Clue Why this is ambiguous. 
    //os_ << tuple_.get<2>();  // Error because no matching operator. Fine. 
    return os_; 
} 

समस्या यह है कि ostringstream ostream है, जो इस हस्ताक्षर हैं से operator<< वारिस है। तब

ostream& operator<<(ostream& os, T t) 

(C++ में सभी उपलब्ध प्रकार के साथ परिवर्तन टी, देखने operator<< reference page

संपादित

यहाँ

एक सरल उदाहरण (एक टपल के बिना) है:

ostringstream& operator<<(ostringstream& os_, Mytuple tuple_) 
{ 
    const int i = tuple_.get<0>(); 
    os_ << i; // error in this line 
    return os_; 
} 

और त्रुटि अब है:

dfg.cpp: In function ‘std::ostringstream& operator<<(std::ostringstream&, Mytuple)’: 
dfg.cpp:18: error: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second: 
/usr/lib/gcc/i386-redhat-linux/4.3.0/../../../../include/c++/4.3.0/bits/ostream.tcc:111: note: candidate 1: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(int) [with _CharT = char, _Traits = std::char_traits<char>] 
dfg.cpp:14: note: candidate 2: std::ostringstream& operator<<(std::ostringstream&, Mytuple) 

ऊपर त्रुटि संदेश का कहना है: यह दो ऑपरेटरों operator<<(ostream&,...) और operator<<(ostringstream&,...). This also raises another question : why on earth do you need ऑपरेटर < < के बीच चयन करने के लिए संभव नहीं है (, ostringstream & ...) `?

+0

क्या आप समझ सकते हैं कि समस्या क्या थी? –

+0

यह काम करता है। लेकिन यह क्यों काम करता है लेकिन 'ostringstream' काम नहीं करता है? दरअसल मैं चाहता हूं कि यह मेरी कस्टम स्ट्रीम के साथ काम करे। – balki

+0

मुझे समझ में नहीं आता है। हां, ओस्ट्रीम ऑपरेटर << आदिम प्रकार के लिए है। एक कस्टम ऑपरेटर के साथ संदिग्ध क्यों होना चाहिए जो एक कस्टम वर्ग लेता है? – balki

3

जब आप लिखना

os << tuple_.get<0>(); 

वहाँ कोई समारोह है कि दोनों मानकों से मेल खाता है। इसके बजाय संकलक या तो पैरामीटर पर एक अंतर्निहित रूपांतरण लागू करने के लिए एक विकल्प है

std::ostream << int 

या

std::ostringstream << MyTuple 

बाद boost::tuple निर्माता कि टपल तत्वों की संख्या पर निर्भर तर्क के किसी भी संख्या ले जा सकते हैं के साथ क्या होगा । (और float साथ यह विफल रहता है, क्योंकि floatint के लिए परिवर्तनीय है।)

जब स्ट्रीम ऑपरेटरों अधिक भार, आधार वर्ग बाएं हाथ की ओर के रूप में (ostream या यहाँ तक कि basic_ostream<CharT, Traits> का उपयोग


संपादित करें:। आप पहले तर्क कास्टिंग करके कॉल को असंबद्ध कर सकते हैं।

ostringstream& operator<<(ostringstream& os_, Mytuple tuple_) 
{ 
    static_cast<std::ostream&>(os_) << tuple_.get<0>(); 
    static_cast<std::ostream&>(os_) << tuple_.get<1>();  
    static_cast<std::ostream&>(os_) << tuple_.get<2>();  // Error because no matching operator. Fine. 
    return os_; 
} 

हालांकि, ostringstream साथ ऑपरेटर ओवरलोडिंग अभी भी एक बुरा विचार है क्योंकि यह ऑपरेटर श्रृंखलन साथ काम नहीं करेंगे है।

MyTuple a, b; 
ostringstream ss; 
ss << a << ' ' << b; 

लागू करेगा:

1) ostringstream& operator<<(ostringstream& os_, Mytuple tuple_)

2) ostream& ostream::operator<<(char)

3) ostream& operator<<(ostream&&, boost::tuple<int,float,Myclass>

+1

लेखन को असंबद्ध करना आसान होगा: 'os.operator << (tuple_.get <1>()); ' – rodrigo

1

उन सभी लोगों को टाइप करने के बजाय के लिए ::std::ostream उपयोग करने के लिए आपको बता रहा ::std::ostringstream पूर्ण हैं सही सही आपको उस तरह से ::std::ostringstream का उपयोग नहीं करना चाहिए।

लेकिन आपके कोड के साथ मेरा मुख्य गोम सामान्यता की परेशानी की कमी है। यह केवल एक विशेष ट्यूपल प्रकार के लिए काम करता है, और उनमें से सभी नहीं।

इसलिए मैंने operator <<::std::tuple के लिए सी ++ 0x में लिखा है जो कि किसी भी टुपल के लिए काम करता है जिसे सदस्यों को व्यक्तिगत रूप से operator << का उपयोग करके लिखा जा सकता है। बूस्ट के टुपल प्रकार के साथ काम करने के लिए इसे शायद अपेक्षाकृत आसानी से अनुवादित किया जा सकता है। संदेश यह है:

template < ::std::size_t fnum, typename tup_type> 
void print_fields(::std::ostream &os, const tup_type &val) 
{ 
    if (fnum < ::std::tuple_size<tup_type>::value) { 
     ::std::cerr << "Fred " << fnum << '\n'; 
     os << ::std::get<fnum, tup_type>(val); 
     if (::std::tuple_size<tup_type>::value > (fnum + 1)) { 
     os << ", "; 
     } 
     print_fields<fnum + 1, tup_type>(os, val); 
    } 
} 

template < ::std::size_t fnum, typename... Elements> 
class field_printer; 

template <typename... Elements> 
class field_printer<0, Elements...> { 
public: 
    typedef ::std::tuple<Elements...> tup_type; 

    static void print_field(::std::ostream &os, const tup_type &val) { 
    } 
}; 

template < ::std::size_t fnum, typename... Elements> 
class field_printer { 
public: 
    typedef ::std::tuple<Elements...> tup_type; 

    static void print_field(::std::ostream &os, const tup_type &val) { 
     constexpr auto tupsize = ::std::tuple_size<tup_type>::value; 
     os << ::std::get<tupsize - fnum, Elements...>(val); 
     if (fnum > 1) { 
     os << ", "; 
     } 
     field_printer<fnum - 1, Elements...>::print_field(os, val); 
    } 
}; 

template <class... Types> 
::std::ostream &operator <<(::std::ostream &os, const ::std::tuple<Types...> &val) 
{ 
    typedef ::std::tuple<Types...> tup_type; 
    os << '('; 
    field_printer< ::std::tuple_size<tup_type>::value, Types...>::print_field(os, val); 
    return os << ')'; 
} 

यह "(element1, element2, ...elementx)" रूप टपल बाहर प्रिंट करता है।

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