c++ - 使用内部 vector 成员创建类作为流访问类实例的容器

标签 c++ c++11 boost std boost-iostreams

提前感谢任何愿意看这个的人的时间。

我想制作一个允许所有流接口(interface)的简单类,但只读/写存储在类中的简单 std::vector。在我尝试自己重写所有内容,然后尝试从 basic_stream 派生之后,在我看来,使用 boost::iostreams 可以最大限度地减少我需要重写的代码量。例如:这是我想做的,但我希望我的类像 os 一样被使用(因此我尝试从 boost::iostreams::stream 派生):http://theboostcpplibraries.com/boost.iostreams-devices

这是一个“第一次尝试”,其中我尝试继承stream和stream_buffer(不知道是否需要)。我只想让流运算符(operator)都使用 std::vector<char>数据作为容器。

//File: memfile2.h
#pragma once

#include <algorithm>                       // copy, min
#include <iosfwd>                          // streamsize
#include <boost/iostreams/categories.hpp>  // source_tag
#include <boost/iostreams/device/array.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/stream_buffer.hpp>

//REV: use boost iostreams to let user write to a local vector of chars
//as a memory file.

//REV: Or just "get" one from the pointer, i.e. have a mem_ptr which "opens" a file.


struct mfile : public boost::iostreams::stream<boost::iostreams::array_source>, boost::iostreams::stream_buffer
{
  std::vector<char> data;

 mfile()
   : boost::iostreams::stream<boost::iostreams::array_source>( data ),
    boost::iostreams::stream_buffer()
    {
    }

  void other_funct()
  {
  }
};

一个示例使用程序是:

#include <memfile2.h>

int main()
{
  mfile f;

  f << "YOLO";

  std::string fromf;
  //f.seekg(0, BOOST_IOS::beg);
  f >> fromf;
  fprintf(stdout, "OUTPUT: [%s]\n", fromf.c_str());

  f.other_funct();
}

最佳答案

以下是三个片段:

继承,非常通用

Live On Coliru

#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/device/back_inserter.hpp>
#include <iostream>
#include <iomanip>
#include <fstream>

template <typename CharT = char, typename CharTraits = std::char_traits<CharT>,
         typename Buffer = std::vector<CharT>,
         typename Base   = boost::iostreams::stream<boost::iostreams::back_insert_device<Buffer> > 
     >
struct basic_fixed_stream : private Buffer, public Base {
    basic_fixed_stream() : Buffer(), Base(*static_cast<Buffer*>(this)) {}

    std::string to_string() const {
        flush(*this);
        return { Buffer::begin(), Buffer::end() };
    }
};

using fixed_stream = basic_fixed_stream<char>;

int main()
{

    fixed_stream f;
    f << "YOLO " << std::showbase << std::hex << std::setfill('0') << 42;

    std::string fromf = f.to_string();
    fprintf(stdout, "OUTPUT: [%s]\n", fromf.c_str());
}

打印:

OUTPUT: [YOLO 0x2a]

更简单,没有继承

Live On Coliru

#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/device/back_inserter.hpp>
#include <iostream>
#include <iomanip>
#include <fstream>

struct fixed_stream {
    template <typename OS=std::ostream> friend fixed_stream& operator<<(fixed_stream& os, OS&(*manip)(OS&)) {
        os._stream << manip;
        return os;
    }

    template <typename T> friend fixed_stream& operator<<(fixed_stream& os, T const& v) {
        os._stream << v;
        return os;
    }
    std::string to_string() const {
        flush(_stream);
        return { _buffer.begin(), _buffer.end() };
    }

    operator std::ostream&() { return _stream; }
  private:
    using buffer_t = std::vector<char>;
    buffer_t _buffer;
    boost::iostreams::stream<boost::iostreams::back_insert_device<buffer_t> > _stream { _buffer };
};

int main()
{
    fixed_stream f;
    f << "YOLO " << std::showbase << std::hex << std::setfill('0') << 42;

    std::string fromf = f.to_string();
    fprintf(stdout, "OUTPUT: [%s]\n", fromf.c_str());
}

同样的输出:

OUTPUT: [YOLO 0x2a]

双向:

另一个也有 istream 功能。请注意,这修复了容量(为方便起见):

Note, if you push more than capacity input, the stream state goes bad. You will want to handle errors and/or clear() the state.

Live On Coliru

#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/device/array.hpp>
#include <iostream>
#include <iomanip>
#include <fstream>

template <typename CharT = char, typename CharTraits = std::char_traits<CharT>,
         typename Buffer = std::vector<CharT>,
         typename Base   = boost::iostreams::stream<boost::iostreams::array> 
     >
struct basic_fixed_stream : private Buffer, public Base {
    basic_fixed_stream(size_t capacity = 1024) : Buffer(capacity), Base(this->data(), this->size()) {}

    using Base::clear;

    std::string to_string() const {
        flush(*this);
        return { Buffer::begin(), Buffer::end() };
    }
};

using fixed_stream = basic_fixed_stream<char>;

int main()
{
    {
        fixed_stream f;
        f << "YOLO " << std::showbase << std::hex << std::setfill('0') << 42;

        std::string fromf = f.to_string();
        fprintf(stdout, "OUTPUT: [%s]\n", fromf.c_str());
    }

    {
        fixed_stream f;
        {
            std::ifstream ifs("main.cpp");
            f << ifs.rdbuf();
        }
        f.clear();
        f.seekg(0);

        std::string line;
        while (getline(f, line))
            fprintf(stdout, "OUTPUT: [%s]\n", line.c_str());
    }


}

输出:

OUTPUT: [YOLO 0x2a]
OUTPUT: [#include <iostream>]
OUTPUT: [#include <boost/spirit/home/x3.hpp>]
OUTPUT: [#include <boost/fusion/adapted/std_tuple.hpp>]
OUTPUT: [#include <boost/spirit/home/x3/binary.hpp>]
OUTPUT: []
OUTPUT: [namespace x3 = boost::spirit::x3;]
OUTPUT: []
OUTPUT: [namespace hessian {]
OUTPUT: []
OUTPUT: [    typedef std::string string_t;]
OUTPUT: []
OUTPUT: [    namespace parser {]
OUTPUT: []
OUTPUT: [        struct bstring : x3::parser<bstring> {]
OUTPUT: [            using attribute_type = hessian::string_t;]
OUTPUT: []
OUTPUT: [            // string ::= s b1 b0 <utf8-data> string]
OUTPUT: [            //       ::= S b1 b0 <utf8-data>]
OUTPUT: [            //       ::= [x00-x1f] <utf8-data>]
OUTPUT: [            // NOTE: The length means number of UTF16 characters but the content is given in UTF8 characters!]
OUTPUT: [            template <typename It, typename Ctx, typename Attr>]
OUTPUT: [                bool parse(It& f, It const& l, Ctx&, x3::unused_type, Attr& attr) const {]
OUTPUT: [                    auto saved = f;]
OUTPUT: [                    char type;]
OUTPUT: [                    size_t len;]
OUTPUT: [                    auto tied = std::tie(type, len);]
OUTPUT: []
OUTPUT: [                    while (x3::parse(f,l,x3::char_("sS") >> x3::big_word,tied)) {]
OUTPUT: [                 ]

您会注意到这是源代码的第一个千字节!

关于c++ - 使用内部 vector 成员创建类作为流访问类实例的容器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35337612/

相关文章:

c++ - boost IPC 等效(qt?)

c++ - 如何从 Main 调用 void 函数

c++ - C++中的静态变量声明和定义

c++ - 没有原始指针返回二进制数据的通用方法

c++ - 为 vector 中的所有对象动态调用 C++ 类成员

c++ - 为什么要将友元函数定义为结构的一部分 - boost thread_data?

c++ - 删除和修改 Boost MultiIndex 容器中的元素

python - Boost.Python 中的基类和派生类

c++ - gdb 将内存地址解释为对象

c++ - 为什么 std::declval 添加引用?