首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我应该如何在API中替换vector<uint8_t>::const_iterator?

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

Stack Overflow用户
提问于 2019-04-13 22:13:26
回答 3查看 1.4K关注 0票数 18

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

代码语言:javascript
复制
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函数,传递其向量的迭代器。
  3. 如果返回的Resultnew_buffer_begin与传递给decodebuffer_begin相同,这意味着缓冲区中没有足够的数据来解码任何内容,调用方应该返回到步骤1。否则,调用方将消耗已解码的MetadataPacket对象,并返回到步骤2,在下一次访问中使用new_buffer_begin

我不喜欢这个界面,需要帮助改进:

  • 使用vector<uint8_t>::const_iterator似乎过于具体。有没有一种更通用的方法不强迫调用者使用vector?我正在考虑仅仅使用C风格的接口;一个uint8_t *和一个长度。是否有一个相当通用的C++替代方案?
  • 如果有足够的数据来解码某些内容,那么只有metadata packet会有一个值。我认为std::variant或2个回调(每种类型一个)将使这段代码更自文档化。不过,我不确定哪一个更地道。每种方法的优缺点是什么,是否有更好的方法?
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-04-13 22:26:50

我同意授权vector是不适当的,并赞扬您使界面更有用的尝试。

如果decode需要一个连续的uint8_t序列,经过尝试和测试的(也是最灵活的)解决方案只是接受一个const uint8_t*和一个std::size_t (或者另外两个指针,但指针和长度更惯用)。

在C++20中,您可以使用std::span类型的一个参数来完成此操作。或者回到指针,如果您真的想为此使用现代的库工具,可以将人与std::experimental::observer_ptr混为一谈。

您还可以考虑让decode成为一个模板,它可以接受任何迭代器对,并且(如果需要连续的话)强制要求(即使只是通过文档)迭代器反映一个连续序列。但是,让任何东西都成为模板并不总是你想要的,而且它也并不总是有用的。

票数 18
EN

Stack Overflow用户

发布于 2019-04-13 22:38:14

除了@Justin对跨度的有效建议

  • 您还可以考虑使用std::byte而不是uint8_t,因此:结果解码(std::span缓冲区); 或者,如果您在C++17中,使用来自C++指南支持库:#include //等的span实现。结果解码(gsl::span缓冲区);
  • 如果您希望支持从原始内存以外的容器中解码,请使用任意迭代器(在C++17和更早的版本中)或可能的范围(在C++20中)。迭代器版本: 模板结果解码( InputIt start,InputIt end) { /*等*/ }
  • 值得怀疑的是,Decoder继承的是Codec,而不是相反的。
  • 回调是否是一个很好的选择这个问题(对我来说)在没有看到代码的情况下很难回答。但是,确实要使用std::variant来表示有包或元数据的事实;如果使用变体的std::visit代替回调,也可以“组合”替代方案。
票数 15
EN

Stack Overflow用户

发布于 2019-04-13 22:23:14

C++20将有std::span,它可以满足您的需要:

代码语言:javascript
复制
    Result decode(std::span<uint8_t const> buffer);

std::span<T>在语义上等同于T* buffer, size_t size

在C++17中,有一些与std::span等价的span类型的实现,例如GSL's gsl::span。见什么是“跨度”,什么时候应该使用?

如果您不能使用任何外部库,请考虑编写自己的span类型,否则uint8_t const* buffer_begin, uint8_t const* buffer_end可以工作。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55670315

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档