C++ Protobuf生成的message类是否提供empty()、size()这类成员方法?
问题回答
原生Protobuf生成的C++消息类默认不支持你描述的empty()、size()成员方法调用,不过可以通过二次封装轻松实现该需求,细节如下:
- 原生API已支持的能力:
Clear()方法是Protobuf生成类默认自带的,无需额外开发即可直接调用,作用就是清空消息所有已设置的字段值。 - 缺失能力的实现方案:
你要的empty()(判断所有字段是否均未设置)、size()(统计已设置的字段数量)可以基于Protobuf的反射接口封装实现,你可以选择做全局辅助函数或者轻量包装类两种形式:- 全局辅助函数实现(无侵入,无需修改原有消息类逻辑):
调用示例:#include <google/protobuf/message.h> // 判断消息是否为空(所有字段均未设置) bool is_proto_empty(const google::protobuf::Message& msg) { return msg.ByteSizeLong() == 0; } // 统计消息已设置的字段数量 size_t count_set_fields(const google::protobuf::Message& msg) { size_t cnt = 0; const auto* desc = msg.GetDescriptor(); const auto* refl = msg.GetReflection(); for (int i = 0; i < desc->field_count(); i++) { const auto* field = desc->field(i); if (refl->HasField(msg, field)) cnt++; } return cnt; }Person p; assert(is_proto_empty(p)); p.set_age(10); assert(count_set_fields(p) == 1); p.Clear(); assert(is_proto_empty(p));- 包装类实现(可完全对齐你期望的调用格式):
调用方式完全符合你写的示例:class PersonWrap { public: bool empty() const { return _msg.ByteSizeLong() == 0; } size_t size() const { size_t cnt = 0; const auto* desc = _msg.GetDescriptor(); const auto* refl = _msg.GetReflection(); for (int i = 0; i < desc->field_count(); i++) { const auto* field = desc->field(i); if (refl->HasField(_msg, field)) cnt++; } return cnt; } void Clear() { _msg.Clear(); } // 按需透传其他set/get方法即可 void set_age(int32_t age) { _msg.set_age(age); } int32_t age() const { return _msg.age(); } private: Person _msg; };PersonWrap p; assert(p.empty()); p.set_age(10); assert(p.size() == 1); p.Clear(); assert(p.empty());
内容的提问来源于stack exchange,提问作者PeopleMoutainPeopleSea
相关产品推荐
相关产品推荐

