如何创建过滤流的成员向量?
How to create a member vector of filtering streams?
让我们从一个简单的压缩文件开始 reader class 使用 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
我想扩展我的 class 以类似的方式读取和操作多个文件。下面是我试过的示例代码(也在上面的 Coliru link 中注释掉了):
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;
};
由于基础 classes 中缺少复制构造函数,上述代码无法编译。我试过使用 boost::optional
、std::shared_ptr
和其他用于延迟初始化的替代方法。到目前为止,唯一可行的解决方案是为 std::vector
使用初始化列表构造函数,即执行 ctor: m_stream(filenames.size()) {...}
。我有 2 个问题:
- 为什么这里还要调用拷贝构造函数?
- 没有初始化列表的方式是否可以做到这一点?
Why is a copy constructor even being called here?
这里:
m_stream.emplace_back(s);
Is it possible to do this without the initializer list way?
选项 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;
For循环代码:
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]});
}
}
有了这个,您以后就不能添加或删除流。如果需要这些功能,请使用其他选项。
让我们从一个简单的压缩文件开始 reader class 使用 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
我想扩展我的 class 以类似的方式读取和操作多个文件。下面是我试过的示例代码(也在上面的 Coliru link 中注释掉了):
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;
};
由于基础 classes 中缺少复制构造函数,上述代码无法编译。我试过使用 boost::optional
、std::shared_ptr
和其他用于延迟初始化的替代方法。到目前为止,唯一可行的解决方案是为 std::vector
使用初始化列表构造函数,即执行 ctor: m_stream(filenames.size()) {...}
。我有 2 个问题:
- 为什么这里还要调用拷贝构造函数?
- 没有初始化列表的方式是否可以做到这一点?
Why is a copy constructor even being called here?
这里:
m_stream.emplace_back(s);
Is it possible to do this without the initializer list way?
选项 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;
For循环代码:
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]});
}
}
有了这个,您以后就不能添加或删除流。如果需要这些功能,请使用其他选项。