我的任务是完善编解码器库的界面。我们使用的是 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
,然后通过
从文件中读取一大块数据(但将来可能会有其他来源),并将其附加到
vector<uint8_t>
.调用
decode
函数,传递其 vector 的迭代器。如果返回
Result
的new_buffer_begin
与buffer_begin
相同已传递给decode
,这意味着缓冲区中没有足够的数据来解码任何内容,调用者应返回步骤 1。否则,调用者会使用Metadata
或Packet
已解码的对象,并返回到第 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/