让我们从使用boost::iostreams
的简单压缩文件读取器类开始:
class SingleFileOpener{
public:
SingleFileOpener(const std::string& filename, bool is_compressed) {
if(is_compressed) m_stream.push(bio::zlib_decompressor());
m_stream.push(bio::file_source{filename});
}
void print() {
bio::copy(m_stream, std::cout);
}
private:
using unseekable_stream = boost::iostreams::filtering_istream;
unseekable_stream m_stream;
};
现在依次调用SingleFileOpener("input.txt", true)
和print()
可以正常工作。 Coliru Link
我想扩展我的课程,以类似的方式读取和操作多个文件。下面是我尝试过的示例代码(也在上面的Coliru链接中进行了注释):
class MultiFileOpener{
public:
MultiFileOpener(const std::vector<std::string> filenames, std::vector<bool> is_compressed) {
for(auto i = 0u; i < filenames.size(); i++) {
unseekable_stream s;
if(is_compressed[i]) s.push(bio::zlib_decompressor());
s.push(bio::file_source{filenames[i]});
m_stream.emplace_back(s); // <- error: use of deleted function(copy ctor)
}
}
void print(int i) {
bio::copy(*m_stream[i], std::cout);
}
private:
using unseekable_stream = boost::iostreams::filtering_istream;
std::vector<boost::optional<unseekable_stream>> m_stream;
};
由于基类中缺少复制构造函数,因此上述内容无法编译。我尝试使用boost::optional
,std::shared_ptr
和用于延迟初始化的其他替代方法。到目前为止,唯一有效的解决方案是对std::vector
使用初始化列表构造器,即执行ctor: m_stream(filenames.size()) {...}
。我有两个问题:
答案 0 :(得分:1)
为什么还要在这里调用复制构造函数?
这里:
m_stream.emplace_back(s);
有没有初始化列表方法的方法吗?
选项1
使用列表:
std::list<unseekable_stream> m_stream;
按如下所示更改for循环:
m_stream.emplace_back();
auto& s = m_stream.back();
if(is_compressed[i]) s.push(bio::zlib_decompressor());
s.push(bio::file_source{filenames[i]});
选项2
使用unique_ptr
:
std::vector<std::unique_ptr<unseekable_stream>> m_stream;
对于循环代码:
auto stream_ptr = std::make_unique<unseekable_stream>();
... //same as above but change . to ->
m_stream.push_back(std::move(stream_ptr));
选项3
使用大小初始化向量,而不使用push_back
或emplace_back
。
std::vector<unseekable_stream> m_stream;
MultiFileOpener(const std::vector<std::string>& filenames, const std::vector<bool>& is_compressed)
: m_stream(filenames.size())
{
for(auto i = 0u; i < filenames.size(); i++) {
unseekable_stream& s = m_stream[i];
if(is_compressed[i]) s.push(bio::zlib_decompressor());
s.push(bio::file_source{filenames[i]});
}
}
有了这个,您以后就不能添加或删除流。如果需要这些功能,请使用其他选项。