解决由于C ++而在Google protobuf中解决枚举字段命名限制的解决方案

时间:2014-11-20 01:42:04

标签: java c++ serialization enums protocol-buffers

正如您所知,当您使用全局范围或相同的消息在Google protobuf中定义枚举时,如果枚举是兄弟,则无法将枚举字段名称定义为相同。

即使您要使用proto文件生成Java代码,protoc也会抱怨它,并且生成任何带有以下消息的代码。

"XXX" is already defined in "your.package.name".
Note that enum values use C++ scoping rules, meaning that enum values are siblings of their type,
not children of it. 
Therefore, "XXX" must be unique within "your.package.name", not just within "your_enum_name".

所以,这意味着你应该做一些像

这样的事情
  1. 用冲突包装碰撞的枚举。
    • 优点:嗯...... protoc没有失败?
    • 缺点:生成代码将有一个额外的静态包装类,因此它会稍微增加SerDes成本+命名似乎足够长。例如,CURRENCY.NAMESPACE(包装器消息名称).USD
    1. 为字段使用前缀,因此如果您的冲突字段名称为UNKNOWN且其为CURRENCY,则它将为CURRENCY.CURRENCY_UNKNOWN或类似名称。
      • 优点:简单
      • 缺点:与#1一样丑陋,与现有的没有任何前缀的枚举字段命名不一致。
      1. 不要使用Enum。使用字符串类型。
        • 优点:简单,不需要像UNKNOWN = 1那样定义回退枚举字段作为默认值。
        • 缺点:失去恩惠的好处。
      2. 似乎C ++ 11支持没有这个问题的更好的枚举,但遗憾的是最新的protoc并不支持它,我们不能简单地要求其他消费者转换他们的一面使用C ++如果他们没有使用它。

        所以,它会选择不那么糟糕的解决方案而不是最佳解决方案,而且我们可能会在这一点上使用#2。有没有人有相同的经验,告诉我你的解决方案是什么?它是如何结束的?

1 个答案:

答案 0 :(得分:11)

现有代码中的主流解决方案是选项(2):为每个枚举名称指定与其类型对应的前缀。这也有助于减少与宏的冲突。它很冗长,但与其他建议的选项不同,它没有运行时开销,并且对于阅读代码的人来说创建的混乱最少。

(FWIW,Cap'n Proto通过使用C ++ 11枚举类逃脱了这个问题。由于它会破坏现有代码,所以protobufs不太可能这样做。)

(披露:我是Cap'n Proto的作者以及Google的大部分开源Protobuf代码。)