问题:
#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_stream<_Elem,_Traits>::运算符<lt;':5个过载具有类似的转换
我做错了什么,还是这是另一个MS Visual Studio错误?
解决方法:添加以下成员方法似乎有效,但我希望深入了解根本原因。
MyClass& operator<<(const char* str) {
std::ostream& os = *this;
os << str;
return *this;
}
背景:MySql++不使用Visual Studio 2010进行编译(请参阅邮件列表),因为VS2010不支持std::ostream的公共继承。作为一个变通办法,我正在尝试私人继承,因为这比合成少了黑客攻击。MyClass;运算符<lt;(const char*str){std::ostream&os=*这个;os<lt;str;return*this;}
完整错误消息
1>d:repotesttestmain.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.0vcincludeostream(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.0vcincludeostream(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.0vcincludeostream(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.0vcincludeostream(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.0vcincludeostream(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])'
只需转发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
的成员函数。使用声明不会导入这些。
这是流插入器的定义方式有点奇怪的结果。有的是ostream
的成员;这些是通过using声明获得的。有些是免费函数;这些需要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
,从公共继承开始,并实现适当的重写。
澄清一下,你指的是
using std::ostream::operator<<;
而不是
using std::operator<<;