2011-05-13 54 views
10

说我有A级和运营商宣布像这样< <:如何重载ostream运算符<<以使其在C++中使用log4cxx?

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

别的地方我用我的记录器使用A:

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

编译器抱怨: 二进制“< < ':找不到操作符,它的右手操作数是'const A'(或者没有可接受的转换)D:\ dev \ cpp \ lib \ apache-log4cxx \ log4cxx \ include \ log4cxx \ helpers \ messagebuffer.h 190

此错误带我到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宏展开:

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

MessageBuffer “定义” 这个操作符,以及:

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

我不明白如何以正确的方式使运营商超负荷工作。任何想法?

+0

哪个编译器? – 2011-05-13 11:09:58

+0

@Alan Stokes:我正在使用Visual Studio 2010 – 2011-05-13 11:20:52

+0

尝试在messagebuffer.h之前添加A.h – 2011-05-13 12:18:37

回答

7

你可以尝试宣告您的运营商< < std下(这是合法的,因为你通过你的用户定义类型的实例):

namespace std { 
    ostream& operator<<(ostream& os, const A& a); 
} 
+0

我不习惯把一个不属于我的命名空间加以警告,但我应该承认它像一个魅力一样工作!干杯。 – 2011-05-13 14:09:35

+0

我有兴趣了解编译器在此情况下无法找到我的操作符的原因。 – 2011-05-13 14:11:13

+0

我也是!我认为ADL(依赖于参数的查找)应该让你的代码正常工作;但ADL充满了微妙之处,而Visual Studio增加了自己的特质。命名空间std技巧已经为我工作过。一旦你习惯了它,它并不像看起来那么糟糕。 – 2011-05-13 19:06:54

0

我现在没有编译器可用,但我认为问题是由于尝试在常量字符串上使用插入运算符造成的。 "A: " << a

+1

我没有插入一个常量字符串;你必须误读'LOG4CXX_INFO'扩展。 – 2011-05-13 12:28:14

2

把艾伦的建议已定义的用户std命名空间中的运算符起作用。但我更喜欢将用户定义的运算符放在log4cxx::helpers命名空间中,这也适用。具体而言,

namespace log4cxx { namespace helpers { 
    ostream& operator<<(ostream& os, const A& a); 
} }