std::ostream 和使用运算符的私有继承<<



问题:

#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&lt_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::stringstd::complex或任何用户定义的类型)没有帮助。

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

澄清一下,你指的是

using std::ostream::operator<<;

而不是

using std::operator<<;

相关内容

  • 没有找到相关文章