2014-05-18 77 views
3

在我的项目中,我使用了一个名为Message的类,它从std :: ostringstream继承来打印出其他类类型的可读信息。继承自std :: ostringstream

因此,它的< <运算符被重载了好几次,我想要打印出我自己的类类型。

class Message : public ostringstream 
{ 
public: 
    Message() {}; 
    virtual ~Message() {}; 

    Message& operator <<(const MyTypeA &a) { return *this << a.getStr(); }; 
    Message& operator <<(const MyTypeB &b) { return *this << b.identifier(); }; 
    Message& operator <<(const MyTypeC &c) { return *this << c.foo(); }; 

    // Pass everything unknown down to ostringstream, and always return a Message& 
    template<class T> 
    Message& operator <<(const T &t) 
    { 
     (std::ostringstream&)(*this) << t; 
     return *this; 
    } 
}; 

没有模板

MyTypeA a,b; 
Message m; 
m << a << "-" << b; 

代码将不编译,为(M < <一个< < “ - ”)将返回一个ostringstream &这将不能够采取 'B' 。所以我使用模板来确保始终返回消息&。

我的问题:

Message m; 
m << "Hello, world" << std::endl; 

生成veeery长的编译器错误,我不知道为什么。

Here是我的问题的简约“不”可编译的例子,而here是相应的编译器输出。

+1

这里是错误的关键部分:*不能推导出模板参数“T” * – chris

+7

何不你是否实现了ostringstream&operator <<(ostringstream&os,const MyTypeA&a)'而不是? – pts

+4

相关:http://stackoverflow.com/q/1134388/951890 –

回答

8

不是派生自任何流类创建一个新的流!来自std::ostreamstd::istream的唯一原因是创建一个正确设置为使用合适流缓冲区的流。您应该从std::streambuf派生出一个新的来源或目的地,而不是从流派生出来。要为新类型创建输出运算符,您会将operator<<()std::ostream&作为第一个参数并将您的自定义类型作为第二个参数来重载。同样与std::istream&

顺便说一句,你遇到的问题是因为std::endl是一个函数模板。试图在某个地方传递函数模板需要适当的实例化。由于您的输出运算符不包含合适的签名,因此无法推导出std::endl的实例。我可以说明需要什么,但这是毫无意义的,因为无论如何这都是错误的方式。

1

这里是如何让你的代码编译:http://pastebin.com/xAt5junf

相关摘录:

class Message : public ostringstream 
{ 
public: 
    Message() {}; 
    virtual ~Message() {}; 
}; 

ostream& operator <<(ostream &os, const MyTypeA &a) { 
    return os << a.getStr(); 
}; 

ostream& operator <<(ostream &os, const MyTypeB &b) { 
    return os << b.getStr(); 
};