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

时间:2012-09-13 03:14:52

标签: c++ visual-studio mysqlpp

问题:

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

3 个答案:

答案 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::stringstd::complex或任何用户定义的类型等其他类型无效。

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

答案 2 :(得分:0)

只是澄清,你的意思是

using std::ostream::operator<<;

而不是

using std::operator<<;