0

问题:

#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>::operator <<' : 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& 运算符<<(const char* str) { std::ostream& os = *this; 操作系统 << str; 返回*这个;}

完整的错误信息

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])'
4

3 回答 3

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. 使用声明不会导入那些。

于 2012-09-13T12:19:52.617 回答
1

这是定义流插入器的方式有点怪异的结果。有些是ostream; 这些是被 using 声明拾取的那些。有些是免费功能;那些采用stream&(嗯,正式地,a basic_ostream<charT>&),它们不适用于您的类型。这就是为什么c << 'a'可以(插入器 forchar是 的成员ostream),而c << "Hello, world!"不是(插入器 forchar*不是成员函数;它需要stream&在其左侧)。而在 中,子表达式c << 'a' << "Hello, world!"的返回类型是,所以下一个插入器看到的是 an而不是 a ,所以此时就可以了。c << 'a'ostream&ostream&MyClass

您的解决方法避免了 的问题char*,但对其他类型(如 、 或任何用户定义的类型)没有std::string帮助std::complex

正确的答案是,如果你想创建一个可以代表 an 的类型,ostream你必须将它实现为ostream,从公共继承开始,并实现适当的覆盖。

于 2012-09-13T12:12:41.367 回答
0

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

using std::ostream::operator<<;

而不是

using std::operator<<;
于 2012-09-13T04:35:54.987 回答