No match for operator<< when using std::endl

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • JerryBrit
    New Member
    • Mar 2010
    • 2

    No match for operator<< when using std::endl

    When compiling the below I get the following error:
    no match for 'operator<<' in 'log << std::endl' main.cpp

    Why can't I use std::endl in my class?

    Code:
    #include <iostream>
    
    class Logger {
            public:
                    template <typename T>
                    Logger& operator << (const T &t)
                    {
                    	// do sth with t
                    	std::cout << t;
                    	return *this;
                    }
    };
    
    int main()
    {
    Logger log;
    
    log << "Hello " << 10 << 20;  // ok
    log << std::endl; // fault here
    
    }
  • weaknessforcats
    Recognized Expert Expert
    • Mar 2007
    • 9214

    #2
    The operator<< cannot be a member function. This is because the first argument of the << function must be the object to the left of the operator and the second argument is the object to the right of the operator. LIke this:

    Code:
    ostream& operator<<(ostream& os, Logger& obj);
    As a member function, the compiler will insert the this pointer of your Logger object as the first argument. That would be a pointer to a Logger object. std::endl requires an ostream& and not a Logger*.

    The solution is to make your operator<< a friend function. It should have the prototype shown above.

    Comment

    • JerryBrit
      New Member
      • Mar 2010
      • 2

      #3
      Thanks for quick reply weaknessforcats ,

      but declaring the function this way:
      friend ostream& operator<<(ostr eam& os, Logger& obj)
      how can I pass parameters to the Logger class?

      Comment

      • weaknessforcats
        Recognized Expert Expert
        • Mar 2007
        • 9214

        #4
        You have Logger object right?

        Code:
        Logger obj( the parameters);
        
        obj.SetFormat(parameters for formatting the log);
        
        //etc...
        
        cout << obj << endl;

        The code above is a call to

        Code:
        ostream& operator<<(ostream&, Logger&);
        followed by a call to

        Code:
        ostream& operator<<(ostream&, ostream& (*)(ostream&));
        The second call is for the endl. The second function is provided by the C++ Library.

        You could also:

        Code:
        cout << Logger(the parameters) << endl;

        That would create a Logger object which would be used an then deleted when the satement was complete.

        Comment

        • Banfa
          Recognized Expert Expert
          • Feb 2006
          • 9067

          #5
          weaknessforcats my reading of what JerryBrit is trying to do (and I may be wrong) is that they are not trying to output the data in Logger but that the Logger class is an intercept to say log the output of a program as it is running and although it currently outputs to cout it might in future be altered to output to a file or to both cout and a file.

          JerryBrit if my interpretation is wrong you should say because in that case what weaknessforcats is almost certainly right. However if I am right any data in the Logger class is irrelivent and is not being output anyway, Logger needs to receive data in the same way that cout normally does not be capable of being passed to cout.

          I think, but listen to weaknessforcats because he really is the expert, that in that case what you would want is your own logging version of endl defined something like

          Logger& loggerendl ( Logger& os );

          to output an end of line to the log output. Or you would need to define a member function of Logger something like

          Logger& Logger::operato r<<(ostream& ( *pf )(ostream&));

          to accept stream manipulators like endl.

          Comment

          • weaknessforcats
            Recognized Expert Expert
            • Mar 2007
            • 9214

            #6
            You might try:

            Code:
            class Logger { 
            private:
            	ofstream theLog;
            	       public: 
            			Logger();
                            template <typename T> 
                            Logger& operator << (const T &t) 
                            { 
                                // do sth with t 
                                this->theLog << t; 
                                return *this; 
                            } 
            	
            }; 
            Logger::Logger(): theLog("TheLogFile.txt")
            {
            
            }
            
            int main() 
            { 
            Logger log; 
              
            log << "Hello " << 10 << 20;  // ok 
            log << std::endl; // fault here
            Here I added an ofstream object to your Logger. This the log file. Since it is an ofstream and since ofstream is a kind-of ostream, then a manipulator like std::endl should work with an ofstream object.

            Then all I did was add a Logger constructor to get the file name and change your Logger::operato r<< to use the ofstream member variable rather than cout.

            Comment

            Working...