gpt4 book ai didi

c++ - 用 protobuf 枚举替换 C++ 枚举

转载 作者:太空狗 更新时间:2023-10-29 21:17:19 24 4
gpt4 key购买 nike

在我的代码库中,我有没有像下面这样的底层类型的无范围枚举:

enum EFoo {
EF_AAA = 0,
EF_UNKNOWN = 1,
EF_BBB = 2,
EF_MAX
}

我想让它成为一个 protobuf 枚举,这样它就可以在其他 protobuf 消息中直接作为枚举重用,而不是某种 int*。 field 。所以我想象 .proto 文件中的枚举声明如下所示:

enum EFoo {
EF_AAA = 0;
EF_UKNOWN = 1;
EF_BBB = 2;
}

这是一个棘手的部分。随着时间的推移,可能会添加新字段,例如 EF_CCC = 3 , 所以我不能声明 EF_MAX就像在 C++ 代码中一样,因为它会破坏与包含 EFoo 类型字段的序列化消息的二进制兼容性。 .和 EF_MAX在整个代码库的 API 中用作 EFoo 类型变量的未知值和 EF_MAX永远不会序列化。但是,有一个 EFoo_ARRAYSIZE类型 int其语义恰好是EF_MAX .所以我正在考虑更换所有 EF_MAXEFoo_ARRAYSIZE , 但有一件事困扰着我,它需要做一个 static_cast<EFoo>(EFoo_ARRAYSIZE)在某些地方,为了避免编译器警告,根据标准,它将被视为未定义的行为,这可能会导致讨厌的优化和错误。

我的问题是,我该如何解决我的问题?或者我错了,我的解决方案是替换所有 EF_MAXstatic_cast<EFoo>(EFoo_ARRAYSIZE)安全吗?

如果它可能很重要,我说的是 C++11 标准。

最佳答案

Proto3 通过向具有 INT_MIN 和 INT_MAX 值的枚举添加两个“哨兵”值来强制所有枚举为 32 位:

enum Foo {
Foo_FOO = 0,
Foo_BAR = 1,
Foo_Foo_INT_MIN_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32min,
Foo_Foo_INT_MAX_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32max
};

这样做的效果是枚举类型 Foo 将始终使用 32 位整数(或更大)作为其表​​示,因此您可以使用 将任何 32 位值存储到其中>static_casts.

请注意 proto2 没有这样做,因此将 ARRAYSIZE 常量转换为 proto2 中的枚举类型是不安全的。特别是,在 proto2 中,如果您有一个最大值为 127 的枚举,它可能会使用 8 位有符号类型表示。 ARRAYSIZE 值将是 128,这将超出该类型的范围——它可能被视为 -128。或者更糟的是,编译器可能会应用导致完全不可预测的行为的优化。

这就是为什么 proto2 将线路上的未知枚举值视为未知字段,就像字段值根本不存在一样。这种行为让很多人感到困惑,因此 proto3 改为强制枚举为 32 位。 (请注意,proto3 的方法意味着如果您在枚举值上有一个 switch() 语句,它必须有一个默认情况,否则您会收到警告。)

关于c++ - 用 protobuf 枚举替换 C++ 枚举,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33185719/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com