包装 ostream 的正确模板方法

correct template method to wrap a ostream

本文关键字:模板方法 ostream 包装      更新时间:2023-10-16

给定一个类

class ostreamWrapper
{
    private:
        ostream * str;
    public:
        ostreamWrapper operator << (const char *);
}

其中ostream * str将指向 std::cout,ostreamWrapper operator << (const char *)将给定的文本发送到包装的 ostream str

在这种情况下,我只能instance << "const char * text",而不能使用其他可打印的数据。不像直接<< std::cout 或 std::cerr。

如何实现运算符方法,以便它接受任何类型的数据,就像 std::cout 或 std::cerr 直接做的那样?

首先,编写一个公共operator<<模板,以便它可以接受任何类型,并简单地将其转发到包装的ostream

template <class T>
ostreamWrapper& operator<<(T&& x) {
    *str << std::forward<T>(x);
    return *this;
}

其次,为了接受插入流操纵器模板(如 std::endl(,添加第二个公共operator<<,专门接受用于包装ostream的操纵器:

ostreamWrapper& operator<<(ostream& (*manip)(ostream&)) {
    *str << manip;
    return *this;
}

省略第二个重载将导致插入过载的操纵器或操纵器模板失败,并显示"不明确的重载"或类似的错误消息。

请参阅建议的实现示例,它将推断模板参数类型并相应地打印,如果您可以使用 C++11 请参阅@Brian答案:

#include <iostream>
using namespace std;
class ostreamWrapper {
private:
    ostream* str;
public:
    ostreamWrapper(ostream* str_v) : str(str_v) {}
    template <typename T>
    ostreamWrapper& operator<<(const T& t) {
        if (str)
            *str << t;
        return *this;
    }
};
int main() {
    ostreamWrapper osw(&std::cout);
    osw << 1 << " texto " << std::string(" otro texto ") << 1.2345;
    return 0;
}