我想编写一个在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对象导致错误C2664(std: :basic_ofstream构造函数无法将参数从std :: basic_ostream转换为const char *)。我也尝试过使用移动构造函数,但是还有其他问题。任何关于如何解决这个问题的建议将不胜感激。
答案 0 :(得分:2)
此:
StreamContainer(std::ostream& os)
应该是:
StreamContainer(Stream& os)
否则,您的ofstream
实例化会尝试将ofstream&
引用(m_stream
)发送到ostream
(os
)。另一个方向很好,但这是将基类对象分配给派生引用。
由于您无法从构造函数参数中推断出类模板参数,因此这只是一个很好的用例,仅用于引入工厂函数:
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&
。