使类在流上模板化处理std::cout和std::of流

  • 本文关键字:std of cout 处理 c++
  • 更新时间 :
  • 英文 :


我想写一个在Stream上模板化的类StreamContainer:

#ifndef STREAMCONTAINER_HPP
#define STREAMCONTAINER_HPP
#include <string>
#include <iostream>
    template<typename Stream>
    class StreamContainer
    {
    public:
        StreamContainer(std::ostream& os)
            : m_stream(os) {} 
    private:
        Stream & m_stream;
    };
#endif

我认为以下客户端代码会起作用:

#include "StreamContainer.hpp"
#include <fstream>
int main(int argc, char argv[])
{
    std::ofstream ofs;
    ofs.open("c:\code\temp.txt");
    StreamContainer<decltype(std::cout)> coutContainer(std::cout); // C2439
    StreamContainer<std::ofstream> fileContainer(ofs); // C2664
}

但这并不奏效,至少在Visual C++2015中是这样。尝试传递std::cout会导致错误C2439(无法初始化成员),尝试传递std::ofstream对象会导致错误C2 664(std::basic_ofstream构造函数无法将参数从std::basic_stream转换为const char*)。我也尝试过使用move构造函数,但遇到了其他问题。如有任何关于如何解决这一问题的建议,我们将不胜感激。

这:

StreamContainer(std::ostream& os)

应该是:

StreamContainer(Stream& os)

否则,您的ofstream实例化将尝试从ofstream&引用(m_stream)到ostreamos)。另一个方向是可以的,但这是将基类对象指定给派生引用。


由于您不能从构造函数参数中推导类模板参数,因此这是一个很好的用例,可以用来引入一个工厂函数:

template <typename Stream>
StreamContainer<Stream> make_container(Stream& s) {
    return StreamContainer<Stream>{s};
}

这样您就不必重复这些参数,或者更糟的是,使用decltype:

auto coutContainer = make_container(std::cout);
auto fileContainer = make_container(ofs);

或者,实际上,如果不需要任何类型细节,两者都可以是ostream&

最新更新