我有一个派生的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的问题。什么是正确的前进方向?
答案 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;
}
如果您需要格式化其他数据,请使用xalloc
和
iword
或pword
获取它,例如定义一个操纵器:
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
)。