根据CapnProto文档:(注意:我正在使用C++版本)
对于Foo是非原始类型的列表,operator[]和iterator::操作符*()返回的类型是Foo::Reader (用于列表::Reader)或Foo::Builder (用于List::Builder)。构建器的set方法将Foo::Reader作为其第二个参数。
虽然使用"set“对于非原语类型似乎很好:Other stack overflow question for primitives only
对于自动生成的非原语列表,似乎没有"set“函数。我的CapnProto生成是在某种程度上失败了,还是有另一种方法可以在非原语列表中设置元素?
发布于 2018-03-20 21:01:24
有一个"set“方法,但它称为setWithCaveats()
destListBuilder.setWithCaveats(index, sourceStructReader)这是为了让您知道,在设置结构列表的元素时存在一些模糊的问题。这个问题源于这样一个事实,即结构列表并不如您所期望的那样以指针列表的形式表示,而是由一系列“扁平”的连续结构表示,这些结构都是相同大小的。这意味着在初始化列表时为列表中的所有结构分配空间。因此,当您调用setWithCaveats()时,目标空间已经在前面分配,并且您正在将源结构复制到该空间中。
面对不同的版本,这带来了一个问题:源结构可能是使用新版本的协议构建的,其中定义了其他字段。在这种情况下,它实际上可能比预期的要大。但是,根据您编译的协议版本,目标空间已经被分配了。太小了!不幸的是,我们别无选择,只能放弃那些我们不知道的新定义的字段。因此,数据可能会丢失。
当然,在您的应用程序中,您可能知道struct值不是来自较新的版本,或者您不在乎是否丢失了您不知道的字段。在这种情况下,setWithCaveats()会做您想做的事情。
如果您想要小心地保留未知字段,则可能需要查看方法capnp::Orphanage::newOrphanConcat()。此方法可以将一个结构读取器列表连接到一个列表中,这样就不会丢失数据--每个结构的大小等于所有输入结构的最大值。
auto orphanage = Orphanage::getForMessageContaining(builder);
auto orphan = orphanage.newOrphanConcat({list1Reader, list2Reader});
builder.adoptListField(kj::mv(orphan));https://stackoverflow.com/questions/49373700
复制相似问题