I want to delete a node from a boost property tree, but I want to preserve its children and connect them to the parent of the deleted node (i.e. to their grandparent node). Is there an elegant way to achieve this?
Asked
Active
Viewed 1,206 times
2 Answers
4
This might be the most efficient way to move the grandchildren:
std::move(middle.begin(), middle.end(), back_inserter(parent));
Full sample
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
using boost::property_tree::ptree;
using boost::property_tree::read_json;
using boost::property_tree::write_json;
int main() {
std::istringstream iss(R"({ "a" : { "middle" : { "a1":1, "a2":2, "a3":3 }, "more":"stuff" } })");
ptree pt;
read_json(iss, pt);
auto& parent = pt.get_child("a");
auto& middle = pt.get_child("a.middle");
std::move(middle.begin(), middle.end(), back_inserter(parent));
parent.erase("middle");
write_json(std::cout, pt);
}
Sample json output:
{
"a": {
"more": "stuff",
"a1": "1",
"a2": "2",
"a3": "3"
}
}

sehe
- 374,641
- 47
- 450
- 633
-
For this to be effective, doesn't `property_tree` need to support move? (move constructor/move assignment). I didn't find a single `&&` (l-value ref) in the whole source code of `proporty_tree`. Am I missing something? – alfC Sep 23 '17 at 07:13
-
1@alfC Firstly, rule-of-zero means you can have move semantics without a single `&&` sign. Secondly, the iterators point into a multi-index-container (so need to look there). That's is [a missing feature](https://stackoverflow.com/questions/46082394/move-element-from-boost-multi-index-array). For now, `ptree` could add a `splice` operation, which would naturally wrap `multi_index`'s [list operations](http://www.boost.org/doc/libs/1_65_1/libs/multi_index/doc/reference/seq_indices.html#list_operations): I just made a [**draft** implementation](https://github.com/boostorg/property_tree/pull/30) – sehe Sep 23 '17 at 09:48
-
rule zero: good point if there no constructor/destructor or anything and it is implemented in terms of a movable type then you have move for free? is that what you mean? I doubt, whatever the class is, in this case that it has zero special functions. So, in summary are you saying that `ptree` is implemented in terms of `multi_index` but in its turn it doesn't have move implemented yet? I guess your code is still correct, because as soon as move is implement down the road this code will run faster that if written with `std::copy`. – alfC Sep 23 '17 at 09:59
-
Agreed on all accounts, @alfC – sehe Sep 23 '17 at 10:14
-
Just to confirm that this not just a property of ptree iterators... Is this the best way to contruct a complicated tree? Construct the leaf outside and then move it? `{ boost::property_tree::ptree pt_sub; recursive_populate(pt_sub); pt.add_child(name, std::move(pt_sub));}` – alfC Sep 23 '17 at 10:18
-
1I'd suggest `ptree& pt_sub = pt.add_child(name, {}); recursive_populate(pt_sub);` instead @alfC (And no it's not just a property of ptree iterators. `std::set<>` e.g. has the same semantics) – sehe Sep 23 '17 at 10:39
-
Ah, ok, I didn't realize that `add_child would return a reference, I though it returned an iterator and then didn't work with the iterator syntax. – alfC Sep 23 '17 at 11:25
0
I had to do something similar.
I used an iterator with recursion and copied the child before removing the node and branching it back on a newly created one.
But I guess the full copy of each trees before removing to be quite resources-consuming so you can only do it with relatively small trees and it isn't really elegant.

eMixam
- 137
- 1
- 10