2013-02-12 78 views
5

मैं वर्तमान में एक std::stringstream के लिए एक आवरण लिख रहा हूँ और मैं सभी operator<<std::stringstream को मेरी कक्षा के माध्यम से कॉल अग्रेषित करना चाहते हैं के साथ endl। यह अभी ठीक है (इस प्रश्न के लिए धन्यवाद: wrapper class for STL stream: forward operator<< calls), लेकिन इसके साथ अभी भी एक मुद्दा है।सी ++ iostream के लिए आवरण वर्ग, एसटीडी की तरह उपयोग धारा संशोधक :: ऑपरेटर <<

चलो कहते हैं कि मैं निम्नलिखित कोड डालें:

class StreamWrapper { 
private: 
    std::stringstream buffer; 
public: 
    template<typename T> 
    void write(T &t); 

    template<typename T> 
    friend StreamWrapper& operator<<(StreamWrapper& o, T const& t); 

    // other stuff ... 
}; 


template<typename T> 
StreamWrapper& operator<<(StreamWrapper& o, T const& t) { 
    o.write(t); 
    return o; 
} 

template<typename T> 
void StreamWrapper::write(T& t) { 
    // other stuff ... 

    buffer << t; 

    // other stuff ... 
} 

मैं अब ऐसा करते हैं तो:

StreamWrapper wrapper; 
wrapper << "text" << 15 << "stuff"; 

यह सिर्फ ठीक काम करता है। लेकिन अगर मैं std::endl जैसे धारा संशोधक का उपयोग करना चाहता हूं, जो http://www.cplusplus.com/reference/ios/endl के अनुसार एक फ़ंक्शन है, तो मैं बस संकलित नहीं करता हूं।

StreamWrapper wrapper; 
wrapper << "text" << 15 << "stuff" << std::endl; 

क्यों? मैं स्ट्रीम संशोधक को भी कैसे अग्रेषित कर सकता हूं?

+0

संकलन त्रुटि क्या है? –

+0

'ऑपरेटर <<' का ओवरलोड होता है जो फ़ंक्शन लेता है, और उसके बाद उस फ़ंक्शन को स्ट्रीम पर कॉल करता है: http://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt http: //en.cppreference .com/w/cpp/io/manip – BoBTFish

उत्तर

3

this answer देखें।

आप चाहेंगे कि

typedef std::ostream& (*STRFUNC)(std::ostream&); 

StreamWrapper& operator<<(STRFUNC func) // as a member, othewise you need the additional StreamWrappe& argument first 
{ 
    this->write(func); 
    return *this; 
} 
+0

@Mogria संपादन क्यों? 'STRFUNC 'ऑब्जेक्ट्स फ़ंक्शन (पॉइंटर्स) हैं, इसलिए उन्हें सीधे' ओस्ट्रीम 'पर कॉल किया जा सकता है। – rubenvb

+0

क्योंकि इसमें अन्य चीजों की वजह से, मुझे अपनी लेखन विधि से गुज़रना होगा। – MarcDefiant

2

आप अतिरिक्त काम का एक सा कर कर रहे हैं। मैं सामान्य रूप से उपयोग करें:

class StreamWrapper 
{ 
    // ... 
public: 
    template <typename T> 
    StreamWrapper& operator<<(T const& obj) 
    { 
     // ... 
    } 
}; 
एक आधुनिक संकलक के साथ

, सभी ठोस प्रकार के लिए इस चाहिए काम करते हैं। समस्या यह है कि मैनिपुलेटर्स टेम्पलेट फ़ंक्शंस हैं, इसलिए कंपाइलर टेम्पलेट तर्क प्रकार कटौती करने में असमर्थ है। समाधान manipulators के प्रकार के लिए गैर टेम्पलेट भार के प्रदान करना है:

StreamWrapper& operator<<(std::ostream& (*pf)(std::ostream&)) 
{ 
    // For manipulators... 
} 

StreamWrapper& operator<<(std::basic_ios<char>& (*pf)(std::basic_ios<char>&) 
{ 
    // For manipulators... 
} 

प्रकार कटौती manipulators के लिए असफल हो जायेगी, लेकिन संकलक समारोह अधिभार समाधान के लिए इन लेने होंगे।

(ध्यान दें कि आप और भी अधिक, बातों के लिए std::setw(int) तरह की जरूरत हो सकती है।)

+0

क्या आपके पास आर-वैल्यू संदर्भ समर्थन है तो सही अग्रेषण मुहावरे समस्या को कम करता है? –

+0

@Tim मुझे ऐसा नहीं लगता है। मैं हाथ से नहीं देखता कि यह कैसे कुछ बदल जाएगा। स्कॉट मेयर (जो मुझे निश्चित रूप से भरोसा है) के अनुसार, टेम्पलेट नाम पूर्ण-अग्रेषित नहीं किए जा सकते हैं (और मुझे नहीं लगता कि आप इसे एक कंपाइलर में कैसे कार्यान्वित कर सकते हैं), और मैनिपुलेटर्स सभी टेम्पलेट नाम हैं। –

+0

अगर उसने कहा, तो मुझे भी भरोसा है। मैं केवल अपनी याद में अपने दोहराए गए वक्तव्यों में था कि सार्वभौमिक संदर्भ "सबकुछ से बंधे"। –