Заполните список CapnProto не примитивным

Согласно документации CapnProto: (ПРИМЕЧАНИЕ: я использую версию C ++)

Для List, где Foo не является примитивным типом, тип, возвращаемый
оператор [] и итератор :: оператор * () является Foo :: Reader (для
List :: Reader) или Foo :: Builder (для List :: Builder).
Метод set строителя принимает Foo :: Reader в качестве второго параметра.

Хотя использование «set», кажется, работает нормально для не примитивных типов:
Другой вопрос переполнения стека только для примитивов

Похоже, что нет функции set для автоматически генерируемых списков не примитивов. Произошел ли сбой в создании моего CapnProto каким-то образом, или есть другой способ установки элементов в списке не примитивов?

0

Решение

Есть метод «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));
1

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector