派生的basic_ostream:“using”关键字和运算符的模糊重载<<

时间:2013-05-03 16:01:44

标签: c++ inheritance iostream using

我有一个派生的basic_ostream类和一个内联修饰符(类似于setw)。我的流类还应该继承所有运算符<<来自其父母的行为。我得到不同的编译器错误取决于我是否使用“using”关键字:

#include <iostream>

struct modifier { };

template <typename C, typename T=std::char_traits<C> >
struct mystream : public std::basic_ostream<C, T>
{
    // this is where the trouble is
    using std::basic_ostream<C, T>::operator <<;

    inline mystream & operator << (const modifier & mod)
    {
        // ...custom behavior...
        return *this;
    }
};

int main()
{
    mystream<char> foo;
    modifier m;
    foo << "string";  // this fails if the using is present
    foo << 123;       // this fails if the using is absent
    foo << m;
}

当我使用using指令时,编译器对“字符串”输出感到困惑,如果我将其注释掉,就会对整数123输出感到困惑,在这两种情况下都给出了“错误:模糊的重载”。运营商LT;&LT;'”。我有g ++ 4.2.1和g ++ 4.8的问题。什么是正确的前进方向?

2 个答案:

答案 0 :(得分:3)

而不是继承自std :: basic_ostream,仅仅重新实现&lt;&lt;对于使用常规流的修饰符结构:

std::ostream & operator << (std::ostream &stream, const modifier & mod)
{
    // ...custom behavior...
    return stream;
}

你的解决方案似乎过于复杂,但我认为你得到的实际错误来自你的重载&lt;&lt; - 它必须接受两个参数(第一个参数是对流本身的引用)。

答案 1 :(得分:2)

没有using,很明显:编译器找不到任何内容 <<的成员重载,因为你的函数隐藏了 他们。 <<是成员,因此没有using 消失。 <<不是会员,所以它仍然有效。

添加using时:所有成员重载都是 可见,好像他们是你班级的成员。和 "string"将转换为char const*。超载 编译器试图解决的是:

operator<<( mystream<char>, char const* ).

现在考虑一些需要考虑的重载:

std::ostream& mystream::operator<<( void const* );
std::ostream& mystream::operator<<( bool );
std::ostream& operator<<( std::ostream&, char const* );

对于第一个参数(foo,一个mystream),前两个参数 函数是比第三个更好的匹配(因为它们是 完全匹配);对于第二个参数(字符串文字), 第三个功能是更好的匹配。因此:含糊不清。

更一般地说,您的代码存在一些问题。 从根本上说,您通过派生来添加<<运算符。如 你看,它不起作用。也许更重要的是 像:

foo << 123 << m;

无效,因为foo << 123会返回std::ostream&, 不是mystream,而且没有 <<可以使用。{ std::ostream&modifier。您可以添加<<运算符 定义新的自由函数:

std::ostream&
operator<<( std::ostream& dest, modifier const& other )
{
    // ...
    return *this;
}

如果您需要格式化其他数据,请使用xallociwordpword获取它,例如定义一个操纵器:

static int Modifier::modIndex = std::ostream::xalloc();

class mod1
{
    int myModifier;
public: 
    mod1( int m ) : myModifier( m ) {}
    friend std::ostream& operator<<( std::ostream& dest,
                                     mod1 const& mod )
    {
        dest.iword( modIndex ) = myModifier;
        return *this;
    }
};

然后,您可以访问dest.iword( modIndex )以获取此信息 在输出例程中。

iword()会返回long&,对于您的每个实例都会有所不同 流(以及您使用的每个不同索引)。

如果您需要更多信息,可以使用pword代替 iword - pword会返回对void*的引用。如果你 想用它来指向动态分配的内存,不要 忘记注册一个回调来删除它(使用 ios_base::register_callback)。