TreeMutator binding: fix collection binding to support move-only types
unintentionally we used copy construction in the builder expression, wenn passing in the CollectionBinding to the ChildCollectionMutator. The problem is that CollectionBinding owns a shaddow buffer, where the contents of the target collection are moved temporarily while applying the diff. The standard implementation of copy construction would cause a copy of that shaddow buffer, which boils down to a copy of the storage of the target collection. If we want to support move-only types in the collection, most notably std::unique_ptr, we can thus only use the move constructor. Beyond that there is no problem, since we're only ever moving elements, and new elements will be move constructed via emplace() or emplace_back()
This commit is contained in:
parent
d58f8c853a
commit
bada8ecffd
3 changed files with 13 additions and 6 deletions
|
|
@ -128,6 +128,12 @@ namespace diff{
|
|||
, openSub(u)
|
||||
{ }
|
||||
|
||||
// allow move construction only,
|
||||
// to enable use of unique_ptr in collections
|
||||
CollectionBinding(CollectionBinding&&) = default;
|
||||
CollectionBinding(CollectionBinding&) = delete;
|
||||
|
||||
|
||||
|
||||
/* === content manipulation API === */
|
||||
|
||||
|
|
@ -259,9 +265,9 @@ namespace diff{
|
|||
|
||||
|
||||
public:
|
||||
ChildCollectionMutator(BIN wiringClosures, PAR&& chain)
|
||||
ChildCollectionMutator(BIN&& wiringClosures, PAR&& chain)
|
||||
: PAR(std::forward<PAR>(chain))
|
||||
, binding_(wiringClosures)
|
||||
, binding_(forward<BIN>(wiringClosures))
|
||||
, pos_(binding_.initMutation())
|
||||
{ }
|
||||
|
||||
|
|
@ -280,7 +286,7 @@ namespace diff{
|
|||
{
|
||||
if (binding_.isApplicable(n))
|
||||
{
|
||||
binding_.inject (binding_.construct(n));
|
||||
binding_.inject (std::move (binding_.construct(n)));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -411,7 +411,8 @@ namespace diff{
|
|||
* - the _matcher closure_ (CollectionBindingBuilder::matchElement) defines
|
||||
* how to determine, if an implementation data element "matches" a given diff spec
|
||||
* - the _constructor closure_ (CollectionBindingBuilder::constructFrom) defines how
|
||||
* to build a new implementation data element from the spec of an `INS` diff verb
|
||||
* to build a new implementation data element from the spec of an `INS` diff verb.
|
||||
* Note: the result will be moved (move-constructed) into the target container.
|
||||
* - the optional _selector closure_ (CollectionBindingBuilder::isApplicableIf)
|
||||
* allows to limit applicability of this whole binding (layer) to only some
|
||||
* diff specs. E.g., we may set up a binding for elements with value semantics
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ namespace test{
|
|||
using std::string;
|
||||
|
||||
class MockElm;
|
||||
using PMockElm = std::shared_ptr<MockElm>;
|
||||
using PMockElm = std::unique_ptr<MockElm>;
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -252,7 +252,7 @@ namespace test{
|
|||
})
|
||||
.constructFrom ([&](GenNode const& spec) -> PMockElm
|
||||
{
|
||||
return std::make_shared<MockElm>(spec.idi, this->uiBus_); // create a child element wired via this Element's BusTerm
|
||||
return std::make_unique<MockElm>(spec.idi, this->uiBus_); // create a child element wired via this Element's BusTerm
|
||||
})
|
||||
.buildChildMutator ([&](PMockElm& target, GenNode::ID const& subID, TreeMutator::Handle buff) -> bool
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue