我正在为std::stringstream
编写一个包装器,我希望通过我的班级将所有operator<<
次来电转发到std::stringstream
。现在效果很好
(感谢这个问题:wrapper class for STL stream: forward operator<< calls),但仍有一个问题。
假设我有以下代码:
class StreamWrapper {
private:
std::stringstream buffer;
public:
template<typename T>
void write(T &t);
template<typename T>
friend StreamWrapper& operator<<(StreamWrapper& o, T const& t);
// other stuff ...
};
template<typename T>
StreamWrapper& operator<<(StreamWrapper& o, T const& t) {
o.write(t);
return o;
}
template<typename T>
void StreamWrapper::write(T& t) {
// other stuff ...
buffer << t;
// other stuff ...
}
如果我现在这样做:
StreamWrapper wrapper;
wrapper << "text" << 15 << "stuff";
这很好用。但是如果我想使用像std::endl
这样的流修饰符,这是一个根据http://www.cplusplus.com/reference/ios/endl的函数,我根本就不编译。
StreamWrapper wrapper;
wrapper << "text" << 15 << "stuff" << std::endl;
为什么呢?我怎样才能转发流修饰符呢?
答案 0 :(得分:3)
请参阅this answer。
你想要
typedef std::ostream& (*STRFUNC)(std::ostream&);
StreamWrapper& operator<<(STRFUNC func) // as a member, othewise you need the additional StreamWrappe& argument first
{
this->write(func);
return *this;
}
答案 1 :(得分:2)
你似乎在做一些额外的工作。我通常使用:
class StreamWrapper
{
// ...
public:
template <typename T>
StreamWrapper& operator<<( T const& obj )
{
// ...
}
};
使用现代编译器, 应该适用于所有具体的 类型。问题是操纵器是模板功能, 所以编译器无法做模板参数类型 扣除。解决方案是提供非模板重载 对于操纵者的类型:
StreamWrapper& operator<<( std::ostream& (*pf)( std::ostream& ) )
{
// For manipulators...
}
StreamWrapper& operator<<( std::basic_ios<char>& (*pf)( std::basic_ios<char>& )
{
// For manipulators...
}
对于操纵器而言,类型推导将失败,但编译器将失败 将获取这些函数重载解析。
(请注意,对于std::setw(int)
等内容,您可能还需要更多内容。)