2009-07-15 19 views
48

मैं ऑपरेटर < <std :: endl अज्ञात प्रकार का है <<

template <Typename T> 
UIStream& operator<<(const T); 

UIStream my_stream; 
my_stream << 10 << " heads"; 

वर्क्स लेकिन अतिभारित:

my_stream << endl; 

संकलन त्रुटि देता है:

error C2678: binary '<<' : no operator found which takes a left-hand operand of type 'UIStream' (or there is no acceptable conversion)

क्या my_stream << endl काम करने के लिए चारों ओर काम है?

+0

UIStream बारे में कुछ भी जानने के बिना, यह थोड़ा मुश्किल टिप्पणी करने के लिए है। –

+10

और फिर भी, आपको एक रास्ता मिला। :) – notJim

उत्तर

64

std::endl एक समारोह है और std::coutoperator<< को लागू करने std::endl के समान हस्ताक्षर से एक समारोह सूचक लेने के लिए यह इस्तेमाल करता है।

वहां, यह फ़ंक्शन को कॉल करता है, और आगे वापसी मूल्य।

#include <iostream> 

struct MyStream 
{ 
    template <typename T> 
    MyStream& operator<<(const T& x) 
    { 
     std::cout << x; 

     return *this; 
    } 


    // function that takes a custom stream, and returns it 
    typedef MyStream& (*MyStreamManipulator)(MyStream&); 

    // take in a function with the custom signature 
    MyStream& operator<<(MyStreamManipulator manip) 
    { 
     // call the function, and return it's value 
     return manip(*this); 
    } 

    // define the custom endl for this stream. 
    // note how it matches the `MyStreamManipulator` 
    // function signature 
    static MyStream& endl(MyStream& stream) 
    { 
     // print a new line 
     std::cout << std::endl; 

     // do other stuff with the stream 
     // std::cout, for example, will flush the stream 
     stream << "Called MyStream::endl!" << std::endl; 

     return stream; 
    } 

    // this is the type of std::cout 
    typedef std::basic_ostream<char, std::char_traits<char> > CoutType; 

    // this is the function signature of std::endl 
    typedef CoutType& (*StandardEndLine)(CoutType&); 

    // define an operator<< to take in std::endl 
    MyStream& operator<<(StandardEndLine manip) 
    { 
     // call the function, but we cannot return it's value 
     manip(std::cout); 

     return *this; 
    } 
}; 

int main(void) 
{ 
    MyStream stream; 

    stream << 10 << " faces."; 
    stream << MyStream::endl; 
    stream << std::endl; 

    return 0; 
} 

उम्मीद है कि इस आप कैसे इन बातों को काम का एक बेहतर विचार देता है:

यहाँ एक कोड उदाहरण है।

+3

जब आप वोट कम करते हैं तो कृपया एक टिप्पणी छोड़ दें ताकि मैं अपना जवाब सुधार सकूं। – GManNickG

+4

मैंने डाउनवोट नहीं किया है, लेकिन यहां एक महत्वपूर्ण विवरण गायब है: std :: endl एक फ़ंक्शन नहीं है बल्कि एक टेम्पलेट फ़ंक्शन है। इसका अर्थ यह है कि यदि आप जेनेरिक मैनिपुलेटर को ऑपरेटर स्वीकार करने की कोशिश करते हैं << ओवरलोड के रूप में: 'टेम्पलेट mystream और ऑपरेटर << (टी एंड (* एफपी) (टी एंड)) '(यह हस्ताक्षर सभी एसटीएल' basic_stream <> ',' ios_base' और 'basic_ios <> 'मैनिपुलेटर्स) कंपाइलर टेम्पलेट के खिलाफ std :: endl से मिलान नहीं कर पाएगा, क्योंकि यह स्वयं में एक टेम्पलेट है और यह परिभाषित नहीं कर सकता कि टी का अर्थ क्या है। –

+1

धन्यवाद! इससे मुझे एक और सवाल का जवाब देने में मदद मिली। http://stackoverflow.com/questions/2196155 –

4

IOStreams को विस्तारित करने के बेहतर तरीकों के लिए here देखें। (थोड़ा पुराना, और वीसी 6 के लिए बनाया गया है, इसलिए आपको इसे नमक के अनाज के साथ ले जाना होगा)

बिंदु यह है कि मज़दूरों को काम करने के लिए (और अंतराल, जो दोनों आउटपुट "\ n" और फ्लश है एक मज़ेदार) आपको पूर्ण ओस्ट्रीम इंटरफेस को लागू करने की आवश्यकता है।

3

std धाराओं को उप-वर्गीकृत करने के लिए डिज़ाइन नहीं किया गया है क्योंकि उनके पास वर्चुअल विधियां नहीं हैं इसलिए मुझे नहीं लगता कि आप इससे बहुत दूर होंगे। हालांकि आप काम करने के लिए std :: ostream को एकत्रित करने का प्रयास कर सकते हैं।

endl काम करने के लिए आपको लगता है कि एक सूचक-टू-समारोह के रूप में है कि कैसे इस तरह के endl के रूप में manipulators यानी

UStream& operator<<(UStream&, UStream& (*f)(UStream&)); 

या

UStream& UStream::operator<<(UStream& (*f)(UStream&)); 
नियंत्रित किया जाता है लेता है operator<< का एक संस्करण लागू करने की आवश्यकता

अब std::endl एक ऐसा फ़ंक्शन है जो std :: basic_ostream का संदर्भ लेता है और देता है ताकि वह आपकी स्ट्रीम के साथ सीधे काम नहीं करेगा, इसलिए आपको अपना स्वयं का संस्करण बनाना होगा जो वें आपकेमें ई std::endl संस्करण।

संपादित करें: ऐसा लगता है कि जीएमएन का जवाब बेहतर है। वह std::endl भी काम करता है!

+0

मैं इस उत्तर का समर्थन करूंगा: पी – GManNickG

+0

असल में नहीं। यदि आप मेरे आलेख से लिंक्ड आलेख को पढ़ना चाहते हैं, तो आप जानते होंगे कि सभी मज़ेदार कैसे काम करते हैं, न केवल उन लोगों को जिन्हें आपने स्पष्ट रूप से कार्यान्वित किया है। – EFraim

31

समस्या यह है कि std::endl एक फ़ंक्शन टेम्पलेट है, क्योंकि आपका ऑपरेटर << है। तो जब आप लिखें:

my_stream << endl; 

आप ऑपरेटर लिए और साथ ही endl के लिए टेम्प्लेट पैरामीटर निकालना संकलक पसंद करेंगे। यह संभव नहीं है।

तो आपको ऑपरेटर << से मैनिपुलेटर्स के साथ काम करने के अतिरिक्त, गैर टेम्पलेट, अधिभार लिखना होगा। उनके प्रोटोटाइप दिखेगा की तरह:

UIStream& operator<<(UIStream& os, std::ostream& (*pf)(std::ostream&)); 

(वहाँ दो अन्य लोगों, std::basic_ios<char> और std::ios_base, आप भी है जो अगर आप सभी manipulators अनुमति देना चाहते हैं प्रदान करने के लिए द्वारा std::ostream की जगह कर रहे हैं) और उनके कार्यान्वयन बहुत के समान होगा में से एक आपके टेम्पलेट्स में से एक है। वास्तव में, बहुत समान आप अपने टेम्पलेट कार्यान्वयन इस तरह के लिए उपयोग कर सकते हैं कि:

typedef std::ostream& (*ostream_manipulator)(std::ostream&); 
UIStream& operator<<(UIStream& os, ostream_manipulator pf) 
{ 
    return operator<< <ostream_manipulator> (os, pf); 
} 

एक अंतिम टिप्पणी अक्सर एक कस्टम streambuf है लेखन अक्सर लिए एक बेहतर तरीका प्राप्त एक तकनीक के लिए आवेदन प्राप्त करने का प्रयास क्या, आप का उपयोग कर रहे हैं।

+2

+1 यह वही उत्तर है जो मैंने कल प्रदान किया था। अनजाने में इसे नजरअंदाज कर दिया गया है। http://stackoverflow.com/questions/1133739/how-does-ofstream-or-ostream-type-cast-all-types-to-string/1134501#1134501 –

+0

वास्तव में मुझे एक ही समाधान मिला, लेकिन मैंने एक सरल उपयोग किया समारोह शरीर: 'पीएफ (* यह); वापसी * ​​यह; ', लेकिन मैं अपने व्युत्पन्न ostreamer वर्ग के सदस्य के रूप में' op << 'जोड़ता हूं। – TrueY

4

मैं यह मेरी समस्या का समाधान करने के लिए किया था, यहाँ मेरी कोड का हिस्सा है:

template<typename T> 
    CFileLogger &operator <<(const T value) 
    { 
     (*this).logFile << value; 
     return *this; 
    } 
    CFileLogger &operator <<(std::ostream& (*os)(std::ostream&)) 
    { 
     (*this).logFile << os; 
     return *this; 
    } 

main.cpp

int main(){ 

    CFileLogger log();  
    log << "[WARNINGS] " << 10 << std::endl; 
    log << "[ERRORS] " << 2 << std::endl; 
    ... 
} 

मैं यहाँ में संदर्भ http://www.cplusplus.com/forum/general/49590/

आशा मिला यह किसी की मदद कर सकता है।

0

स्वीकार किए जाते हैं जवाब के अलावा, के साथ सी ++ 11 यह प्रकार के लिए operator<< ओवरलोड के लिए संभव है:

decltype(std::endl<char, std::char_traits<char>>) 
संबंधित मुद्दे