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

时间:2019-03-14 22:15:18

标签: c++ c++11 vector boost-iostreams

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

  1. 为什么还要在这里调用复制构造函数?
  2. 是否可以通过没有初始化列表的方式来做到这一点?

1 个答案:

答案 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_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]});
        }
    }

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