2009-09-22 137 views
1

我正在使用CPPUnit在我的程序中測試一個類。這個類(SCriterionVal)有點獨特,因爲它有許多類型的轉換運算符(它本質上是一個動態類型值類)。當我編譯使用CPPUNIT_ASSERT_EQUAL()進行測試的測試用例時,我從其中一個CPPUnit頭文件中收到關於「operator<<不明確」的編譯錯誤。看來它正在用我的類型實例化assertion_traits結構,並且該結構有一個toString()方法,該方法在OStringStream上使用operator<<工作。超載運算符<<用於ostream

由於SCriterionVal可用的各種轉換(其中一些定義了operator<<(如內置類型)),我們假設它是模糊的而不是錯誤。在試圖改變這種狀況,我創造了一個頭非成員函數SCriterionVal與此簽名:

ostream &operator<<(ostream &stream, SCriterionVal val); 

我想通因爲簽名應該是完全匹配的,它會解決歧義。沒有這樣的運氣。我在這裏做錯了什麼?我想我可以專門爲我的類型設計assertion_traits的模板,但我希望能夠解決更普遍的問題,即提供一種方法將我的類放入流中,而不僅僅是迎合測試框架。

+1

英文描述是SOOO比代碼好得多的另一種情況。 – 2009-09-22 18:48:45

+1

我想我們應該創建另一個標籤EBTC(英文是更好然後代碼) – 2009-09-22 18:50:04

+0

馬丁,我認爲你的意見是諷刺。我無法發佈代碼,因爲這違反了我公司的政策。此外,它是一個非常大的類,並使用數十種自定義類型,因此無論如何您都無法編譯它。 – rmeador 2009-09-22 19:01:55

回答

2

嘗試將operator<<定義爲類定義中的朋友內聯函數。我總是發現這種方式最好,特別是對於模板。

例如,Boost.Random定義operator<<exponential distribution的聲明中:

template<class CharT, class Traits> 
    friend std::basic_ostream<CharT,Traits>& 
    operator<<(std::basic_ostream<CharT,Traits>& os, const exponential_distribution& ed) 
    { 
    os << ed._lambda; 
    return os; 
    } 
+0

這是一個我從未見過的有趣技術。該函數實際上是一個方法,還是它仍然是一個函數不附加到一個對象(我不知道這個術語)?我正在編輯現在的變化,所以我會讓你知道它是怎麼回事...... – rmeador 2009-09-22 19:11:08

+0

@meador:'friend'可以接受函數定義而不是聲明。這可能看起來很奇怪(這對我來說確實如此),但這就是它的方式。定義的函數仍然是一個自由函數,即使它是在類中定義的。 – sbi 2009-09-22 20:06:09

+0

我試着用你的模板化basic_ostream返回類型,它抱怨說我的函數是一個返回值的void函數。我猜這與我的編譯器是MSVC++ 6這一事實有關。我用「ostream」而不是模板重新編寫了它,並且仍然得到了我原來的模糊性錯誤。我放棄了...我會給你一個+1,假設你的答案會幫助有合理編譯器的人。 – rmeador 2009-09-22 20:33:35