10

Say I have a class A and an operator<< declared like so:

// A.h
class A
{
    // A stuff
};
std::ostream& operator<<(std::ostream& os, const A& a);

somewhere else I use my logger with A:

LoggerPtr logger(LogManager::getLogger("ThisObject"));
A a;
LOG4CXX_INFO(logger, "A: " << a);

The compiler is complaining: binary '<<' : no operator found which takes a right-hand operand of type 'const A' (or there is no acceptable conversion) D:\dev\cpp\lib\apache-log4cxx\log4cxx\include\log4cxx\helpers\messagebuffer.h 190

This error takes me to the declaration of the operator<<:

// messagebuffer.h
template<class V>
std::basic_ostream<char>& operator<<(CharMessageBuffer& os, const V& val) {
    return ((std::basic_ostream<char>&) os) << val;
}

LOG4XX_INFO macro expands to:

#define LOG4CXX_INFO(logger, message) { \
    if (logger->isInfoEnabled()) {\
       ::log4cxx::helpers::MessageBuffer oss_; \
       logger->forcedLog(::log4cxx::Level::getInfo(), oss_.str(oss_ << message), LOG4CXX_LOCATION); }}

MessageBuffer "defines" this operator as well:

// messagebuffer.h
template<class V>
std::ostream& operator<<(MessageBuffer& os, const V& val) {
    return ((std::ostream&) os) << val;
}

I don't understand how to overload this operator the right way to make it work. Any idea?

mister why
  • 1,967
  • 11
  • 33

3 Answers3

7

You could try declaring your operator << in namespace std (that's legal, since you're passing an instance of your user-defined type):

namespace std {
   ostream& operator<<(ostream& os, const A& a);
}
Alan Stokes
  • 18,815
  • 3
  • 45
  • 64
  • I am not used to polute a namespace that's not mine but I should admit that worked like a charm! Cheers. – mister why May 13 '11 at 14:09
  • I'm interested in understanding why the compiler cannot find my operator in this context. – mister why May 13 '11 at 14:11
  • So am I! I think ADL (argument dependent lookup) should make your code just work; but ADL is full of subtleties, and Visual Studio adds its own idiosyncrasies. The namespace std trick has worked for me before. It's not as bad as it looks, once you get used to it. – Alan Stokes May 13 '11 at 19:06
  • 2
    ADL is only taken into account, if the there are no matches in the nearest enclosing namespace. I learned a lot about this when reading [this](http://www.rosvall.ie/Articles/CppLookup.html). – OK. Jan 26 '12 at 13:00
2

Alan's suggestion of putting the user-defined operator in the std namespace works. But I prefer putting the user-defined operator in the log4cxx::helpers namespace, which also works. Specifically,

namespace log4cxx { namespace helpers {
    ostream& operator<<(ostream& os, const A& a);
} }
Phil
  • 5,822
  • 2
  • 31
  • 60
0

I don't have a compiler available right now but i think the problem is caused by trying to use insert operator on a constant string. "A: " << a

O.C.
  • 6,711
  • 1
  • 25
  • 26