将通用 protobuf 复制到堆上的新对象中

Copying a generic protobuf into a new object on the heap

我想复制一个通用的 const protobuf Message 以供进一步操作。我想到了

Message* myfn(const Message *msg) {
  Message *copy = msg->New();
  copy->CopyFrom(*msg);
  // do stuff
  return copy;
}

这是correct/idiomatic吗?还是有更好的方法(也许是 C++11 特定的)?

这是正确的。

如果你想要类型安全,一点模板魔法可以帮助你:

template<class Msg, 
         std::enable_if_t<std::is_base_of<protobuf::Message,
                                          Msg>::value>>
std::unique_ptr<Msg> clone(const Msg* msg)
{
  std::unique_ptr<Msg> p(msg->New());
  p->CopyFrom(*msg);
  return p;
}

您会看到我已将协议缓冲区对象包装在 unique_ptr 中。这提供了一些异常安全性,并具有可转换为 shared_ptr.

的额外优势

为什么这是个好主意?好吧,考虑一个名为 Foo 的协议缓冲区对象,它有两个名为 bar 和 baz 的字符串成员:

void test(const Foo* source_foo)
{
  // clone and convert the unique_ptr to shared_ptr
  std::shared_ptr<Foo> myclone(clone(source_foo));

  myclone->bar() += " cloned";
  myclone->baz() += " cloned again";

  // get a shared_ptr to the members:
  auto mybar = std::shared_ptr<const std::string>(myclone, &myclone->bar());
  auto mybaz = std::shared_ptr<const std::string>(myclone, &myclone->baz());

  give_away(mybar);
  do_something_else(mybaz);

  // at this point the use_count of myclone is at least 3. 
  // if give_away results in holding on to the shared_ptr 
  // to string then myclone will be kept 
  // alive until the last shared_ptr goes away 

}