2010-11-05 115 views
2

在本question,我嘗試通過使用SBRM/RAII一類流,所以爲什麼在使用operator << via template時需要重載?

SBRM(x) << "test"; 

可以做一些額外的在析構函數,但我的模板知識似乎是有限的。

我已經(爲清楚起見,更簡單)是:

#include <iostream> 
#include <sstream> 

class SBRM 
{ 
public: 
    SBRM(int j) : i(j) {} 
    ~SBRM() { std::cout << "SBRM(" << i << "): " << oss.str() << std::endl; } 

    template<typename T> SBRM& operator<<(T& in) { oss << in; return *this; } 
    // SBRM& operator<<(const long long& in) { oss << std::hex << "0x" << in; return *this; } 
    SBRM& operator<<(const double& in) { oss << in; return *this; } 
    SBRM& operator<<(const void* in) { oss << in; return *this; } 

private: 
    int i; 
    std::ostringstream oss; 
}; 


int main() 
{ 
    std::string ttt = "world"; 
    const int i = 3; 
    SBRM(1) << "Hello"; 
    SBRM(2) << ttt; 
    SBRM(3) << 0x1234567890123ll; 
    SBRM(4) << &i; 
    SBRM(5) << 5; 
    SBRM(6) << 0.23; 
    SBRM(7) << i; 
    SBRM(8) << 5 << ", " << ttt << ", " << &i; 
} 

這類作品:

SBRM(1): Hello 
SBRM(2): world 
SBRM(3): 3.20256e+14 
SBRM(4): 0xbf8ee444 
SBRM(5): 5 
SBRM(6): 0.23 
SBRM(7): 3 
SBRM(8): 5, world, 0xbf8ee444 

,但我主要關注的是:爲什麼編譯器要求我超載模板使用(非字符串)文字?
有沒有任何技巧可以避免這種情況,還是我採取了錯誤的做法? 其他建議,歡迎,因爲我現在使出使用宏

NOT_QUITE_SBRM_MACRO(3, "At least, " << 5 << ", this works"); 

問題被認爲是用gcc 4.1.2。和4.4.3。如果沒有重載函數,我得到:

sbrm-stream.cpp: In function ‘int main()’: 
sbrm-stream.cpp:27: error: no match for ‘operator<<’ in ‘SBRM(3) << 320255973458211ll’ 
sbrm-stream.cpp:10: note: candidates are: SBRM& SBRM::operator<<(T&) [with T = long long int] 
sbrm-stream.cpp:28: error: no match for ‘operator<<’ in ‘SBRM(4) << & i’ 
sbrm-stream.cpp:10: note: candidates are: SBRM& SBRM::operator<<(T&) [with T = const int*] 
... 

回答

12

因爲你期待一個const參數和文字不能作這樣的處理。使其論點const和你的煩惱就會消失:

template<typename T> SBRM& operator<<(T const& in) { oss << in; return *this; } 

正如大衛在他的評論中提到,您使用機械手如endl當需要重載。下面是他們的拍攝:

SBRM& operator <<(std::ostream& (*manip)(std::ostream&)) { 
    oss << manip; // alternatively: manip(os); 
    return *this; 
} 

// same for: 

ostream& operator <<(ios& (*manip)(ios&)); 
ostream& operator <<(ios_base& (*manip)(ios_base&)); 

這涵蓋了所有的parameterless manipulators

我真的不確定<iomanip>的參數化操縱器是如何工作的,但他們似乎返回了一個可以使用通用operator <<變體的代理對象。

+0

長的問題,簡單的答案,但它的作品。謝謝 – stefaanv 2010-11-05 13:58:56

+1

@stefaanv:在事情發展過程中發現問題總是困難得多:)順便說一下,當通過引用/指針傳遞時,總是嘗試使用'const',並且只有在真正需要時纔會將其刪除。在這裏也可以使用'typename boost :: call_traits :: param_type'來根據最有效的內容(即內置的get傳遞)來獲取值或傳遞引用。檢出:http://www.boost.org/doc/libs/1_44_0/libs/utility/call_traits.htm – 2010-11-05 14:14:13

+1

如果你想處理操縱器,你仍然需要提供重載,但是這隻會增加3個帶有函數指針的重載(也許它們可以模板化爲一個,但我不確定) – 2010-11-05 14:16:46

相關問題