如何创建过滤流的成员向量?

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::optionalstd::shared_ptr 和其他用于延迟初始化的替代方法。到目前为止,唯一可行的解​​决方案是为 std::vector 使用初始化列表构造函数,即执行 ctor: m_stream(filenames.size()) {...}。我有 2 个问题:

  1. 为什么这里还要调用拷贝构造函数?
  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_backemplace_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]});
        }
    }

有了这个,您以后就不能添加或删除流。如果需要这些功能,请使用其他选项。