2012-09-13 125 views
0

問題:的std :: ostream的私人繼承和使用operator <<

#include <iostream> 
#include <sstream> 

class MyClass : private std::ostream 
{ 
public : 
    MyClass() : std::ostream(&mBuffer) { } 

    using std::operator<<; 


private: 
    std::stringbuf mBuffer; 
}; 

// In main function, for example 
MyClass c; 
c << 'A' << "Hello, World!"; // Works 
c << "Hello, World!" << 'A'; // ERROR 

錯誤(MS的Visual Studio 2010)是錯誤C2666:「的std :: basic_ostream < _Elem,_Traits> ::操作者< <':5重載有類似的轉換

我在做什麼錯誤或是這是另一個MS Visual Studio的錯誤?

解決方法: 添加以下成員方法似乎可行,但我想深入瞭解根本原因。

MyClass& operator<<(const char* str) { 
     std::ostream& os = *this; 
     os << str; 
     return *this; 
    } 

背景:的MySQL ++不使用Visual Studio 2010(見mailing list),因爲VS2010不支持的公有繼承(除其他事項外)的std :: ostream的編譯。作爲解決辦法,我試圖進行私有繼承,因爲它比組合更少。 MyClass &運營商< <(const char * str){ std :: ostream & os = * this; os < < str; return * this; }

完整的錯誤消息

1>d:\repo\test\test\main.cpp(30): error C2666: 'std::basic_ostream<_Elem,_Traits>::operator <<' : 5 overloads have similar conversions 
1>   with 
1>   [ 
1>    _Elem=char, 
1>    _Traits=std::char_traits<char> 
1>   ] 
1>   d:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(206): could be 'std::basic_ostream<_Elem,_Traits> &std::basic_ostream<_Elem,_Traits>::operator <<(std::_Bool)' 
1>   with 
1>   [ 
1>    _Elem=char, 
1>    _Traits=std::char_traits<char> 
1>   ] 
1>   d:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(467): or  'std::basic_ostream<_Elem,_Traits> &std::basic_ostream<_Elem,_Traits>::operator <<(const void *)' 
1>   with 
1>   [ 
1>    _Elem=char, 
1>    _Traits=std::char_traits<char> 
1>   ] 
1>   d:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(851): or  'std::basic_ostream<_Elem,_Traits> &std::operator <<<char,std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,const _Elem *)' [found using argument-dependent lookup] 
1>   with 
1>   [ 
1>    _Elem=char, 
1>    _Traits=std::char_traits<char> 
1>   ] 
1>   d:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(764): or  'std::basic_ostream<_Elem,_Traits> &std::operator <<<std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,const char *)' [found using argument-dependent lookup] 
1>   with 
1>   [ 
1>    _Elem=char, 
1>    _Traits=std::char_traits<char> 
1>   ] 
1>   d:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(679): or  'std::basic_ostream<_Elem,_Traits> &std::operator <<<char,std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,const char *)' [found using argument-dependent lookup] 
1>   with 
1>   [ 
1>    _Elem=char, 
1>    _Traits=std::char_traits<char> 
1>   ] 
1>   while trying to match the argument list '(MyClass, const char [14])' 
+0

這是完整的錯誤信息嗎?通常模板錯誤較長。如果還有更多請發佈。 – Borgleader

+0

這不是一個模板錯誤消息 - 但它確實列出了5個重載方法。我已經編輯完整性。 – Zero

回答

1

這是一個小怪癖的結果流式插入器的定義方式。有些是ostream的成員;那些是通過使用聲明獲取的。有些是免費功能;那些採取stream&(嗯,正式,basic_ostream<charT>&),他們不會與您的類型一起工作。這就是爲什麼c << 'a'沒問題(char的插件是ostream的成員),而c << "Hello, world!"沒有(char*的插件不是成員函數;它在左手邊需要stream&)。並且在c << 'a' << "Hello, world!"中,c << 'a'子表達式的返回類型爲ostream&,所以下一個插入器看到的是ostream&而不是MyClass,所以在這一點上沒問題。

您的解決方法避免了char*的問題,但對其他類型(例如std::string,std::complex或任何用戶定義類型)無效。

正確的答案是,如果你想創建一個可以代表ostream的類型,你必須實現它作爲ostream,從公開繼承開始,並實現適當的覆蓋。

+0

感謝和按照慣例,如此明顯,一旦它指出! - 爲了記錄我知道正確的答案是公有繼承,但似乎在VS2010中記錄了「不會修復」錯誤,並且我正在單獨追蹤問題。 – Zero

0

只是爲了澄清,你的意思是

​​

而不是

using std::operator<<; 
3

只是向前operator<<,使其做正確的事(TM):

class MyClass : private std::ostream 
{ 
public : 
    MyClass() : std::ostream(&mBuffer) { } 

    template <typename T> 
    MyClass& operator<<(T&& t) 
    { 
     static_cast<std::ostream&>(*this) << std::forward<T>(t); 
     return *this; 
    } 

private: 
    std::stringbuf mBuffer; 
}; 

事實上,一些流運營商的聲明爲(朋友)免費功能,還不如std::ostream成員函數。使用聲明不會導入這些。

相關問題