问题:
#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&lt; _Elem,_Traits&gt; :: operator&lt;&lt;' :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的&安培; operator&lt;(const char * str){ 的std :: ostream的和放; os = * this; os&lt;&lt;海峡; 返回*这个; }
完整错误消息
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 :(得分:3)
只需转发operator<<
,以便它能做到The Right Thing(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
的成员函数。使用声明不会导入那些。
答案 1 :(得分: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
来实现,从公共继承开始,并实现适当的覆盖
答案 2 :(得分:0)
只是澄清,你的意思是
using std::ostream::operator<<;
而不是
using std::operator<<;