Monday, April 25, 2011

Overloading << operator C++ - Pointer to Class

class logger {
 ....
};

logger& operator<<(logger& log, const std::string& str)
{
    cout << "My Log: " << str << endl;
    return log;
}

logger log;
log << "Lexicon Starting";

Works fine, but i would like to use a pointer to a class instance instead. i.e.

logger * log = new log();
log << "Lexicon Starting";

Is this possible? If so what is the syntax? Thanks

Edit: The compiler Error is

error: invalid operands of types 'logger*' and 'const char [17]' to binary 'operator<<'
From stackoverflow
  • Here is the way:

    logger * log = new log();
    (*log) << "Lexicon Starting";
    
  • You'd have to dereference the pointer to your logger object and obviously check if it's not 0. Something like this should do the job:

    
      log && ((*log) << "Lexicon starting")
    

    As a general aside, I would shy away from referencing objects like a logger (which you normally unconditionally expect to be present) via a pointer due to the uncertainty you get with a pointer, AKA is there an object or not?

    workmad3 : Agreed. Create the logger during program initialisation, and then provide a way to get a reference rather than a pointer to it. Alternatively, use std::cerr as your logger by reopening it to point to a file (although this requires some work as its slightly hacky :))
    workmad3 : Oh, and make sure you use correct brackets on this. log && ((*log) << "Lexicon starting") to ensure things go right :)
    Timo Geusch : Good idea, thanks for pointing that out...
  • Depending on the context where you get your logger from, you might want to return a reference instead of a pointer:

    ...
    Logger& logger() {
        return *_pLogger;
    }
    ...
    
    Logger& log = logger();
    log << "...";
    
    anon : Why might he want to do this?
    Ferdinand Beyer : It seems to me that he gets his logger instance from some class structure where it might be more useful to return the reference than the pointer to the internal logger implementation. As I said: 'Depending on the context'.
  • Not really. new log( ) has pointer type, "Lexicon starting" has type const char[16]. You can only overload operators if at least one argument has a user-defined type.

    decasteljau correctly remarked that you could do this via (*log), if you wanted the pointer. I don't like the pointer, however. Andrei Alexandrescu devotes quite a few pages on smart logger singletons in "Modern C++ Design", might be worth to consult that.

  • Why not use a reference?

    logger & log = *(new log()); 
    // the above is abhorrent code that 
    // should be replaced by something meaningful
    
    log << "Lexicon Starting";
    

    if this isn't what you want I'd go with Timo Geusch, even if it is ugly

0 comments:

Post a Comment