用于iostream的C ++包装类,使用流修饰符,如std :: endl和operator<<

时间:2013-02-12 09:56:39

标签: c++ stl wrapper iostream

我正在为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;

为什么呢?我怎样才能转发流修饰符呢?

2 个答案:

答案 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)等内容,您可能还需要更多内容。)