c++ - 我应该如何在 API 中替换 vector<uint8_t>::const_iterator?

标签 c++ c++17 binary-data idioms

我的任务是完善编解码器库的界面。我们使用的是 C++17,我只能使用标准库(即没有 Boost)。目前,有一个Decoder大致如下所示的类:

class Decoder : public Codec {

public:

    struct Result {
        vector<uint8_t>::const_iterator new_buffer_begin;
        optional<Metadata>              metadata;
        optional<Packet>                packet;
    };

    Result decode(vector<uint8_t>::const_iterator buffer_begin,
                  vector<uint8_t>::const_iterator buffer_end);

private:
    // irrelevant details
};

调用者实例化一个 Decoder ,然后通过

向解码器提供数据流
  1. 从文件中读取一大块数据(但将来可能会有其他来源),并将其附加到 vector<uint8_t> .

  2. 调用decode函数,传递其 vector 的迭代器。

  3. 如果返回 Resultnew_buffer_beginbuffer_begin 相同已传递给 decode ,这意味着缓冲区中没有足够的数据来解码任何内容,调用者应返回步骤 1。否则,调用者会使用 MetadataPacket已解码的对象,并返回到第 2 步,使用 new_buffer_begin为下一次传球。

我不喜欢这个界面并需要帮助改进的地方:

  • 使用 vector<uint8_t>::const_iterator似乎过于具体。是否有更通用的方法不强制调用者使用 vector ?我正在考虑只使用 C 风格的界面;一个 uint8_t *和一个长度。有没有相当通用的 C++ 替代方案?

  • 如果有足够的数据来解码某些东西,只有 metadata packet会有一个值。我认为 std::variant或 2 个回调(每种类型一个)将使此代码更具 self 记录性。我不确定哪个更惯用。各有什么优缺点,有没有更好的方法?

最佳答案

我同意强制 vector是不合适的,并为您尝试使界面更有用而鼓掌。

如果 decode期望 uint8_t 的连续序列, 久经考验(也是最灵活)的解决方案就是采用 const uint8_t*std::size_t (或者两个指针,但指针和长度更惯用)。

从 C++20 开始,您可以使用 std::span<const uint8_t> 类型的一个参数来执行此操作。 .或者回到指针,如果你真的想为了它而使用现代库工具,你可以用 std::experimental::observer_ptr 混淆人们。 .

您也可以考虑制作decode一个接受任何迭代器对的模板,并且(如果需要连续性)强制(即使仅通过文档)迭代器反射(reflect) 连续 序列。但是,将所有内容都制作成模板并不总是您想要的,而且它并不总是有用的。

关于c++ - 我应该如何在 API 中替换 vector<uint8_t>::const_iterator?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55670315/

相关文章:

c++ - 应为 ';' - 我从学习资源中复制了这段代码,但它不起作用

C++17模板参数推导之谜

c++ - 为什么 C++17 类模板参数推导失败?

c++ - 重载一组类的加号运算符

javascript - javascript跨浏览器二进制数据处理

c++ - 使用 qFromBigEndian 编译错误

c++ - 通过->语法c++从指针访问函数

audio - 为什么 44100 在十六进制编辑器中以相反的顺序显示在十六进制中?

c++ - vector <unsigned char> 与二进制数据的字符串

c++ - 关于 C 中的 C++ 类访问/操作