2011-05-13 52 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); 
} }