property tree put/erase with const iterator, or how to convert const_iterator to iterator

感情迁移 提交于 2019-12-24 03:55:14

问题


I am using boost 1.55.0 on ubuntu 12.04lts with clang 3.4.

I have a boost::property_tree::ptree whose xml input looks like:

<root>
    <persons>
        <person>
            <name>dad</name>
            <age>43</age>
        </person>
        <person>
            <name>me</name>
            <age>4</age>
        </person>
    </persons>
</root>

So I have a list of nodes with the same tag.

To read them I iterate over the tree, and depending on a condition I want to erase a node. This looks like:

boost::property_tree::ptree pt;
boost::property_tree::read_xml(inputFileName, pt);

boost::property_tree::ptree& persons = pt.get_child("root");
for(boost::property_tree::ptree::const_iterator it = persons.begin(); it != persons.end(); ++it)
{
    std::string name = it->second.get<std::string>("name");
    if(name == "dad")
        // erase that name node from pt
        persons.erase(it->second.find("name"); // this doesn't work
}

[Edit]As the answer from pmr supposes, I wrote the following code:

boost::property_tree::ptree::iterator i = persons.begin();
auto assoc_i = it->second.find("name");
auto ci = persons.to_iterator(assoc_i);
std::advance(i, std::distance<boost::property_tree::ptree::const_iterator>(iterator, ci)); // --> here it hangs
persons.erase(i);

Now it compiles, and the application does not crash, but it hangs at the mentioned position. And I don't know why. [/Edit]

Many thanks in advance.


回答1:


Your issue at hand has little to do with the constness of the iterators, you are simply erasing with the wrong ptree iterator.

ptree& persons = pt.get_child("root.persons");
for(auto it = persons.begin(); it != persons.end();) {
   if(it->second.get<string>("name") == "dad")
        it = persons.erase(it);
    else
        ++it;
}

The ptree uses a multi_index for sub-nodes, and to keep an iteration stable over erasures, you must use the iterator returned from the erase() operation to continue the iteration, a common pattern.

Note that the XML in the question has an / (</age>) termination missing, it wouldn't validate. I am not editing the question to fix it since this could be one of the problems that you experience with the execution of the program.

Output of processing the ptree with the above code via write_xml(std::out, pt):

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <persons>
    <person>
      <name>me</name>
      <age>4</age>
    </person>
  </persons>
</root>



回答2:


C++11 APIs for containers specify a member function iterator container::erase(const_iterator, const_iterator). Unfortunately, basic_ptree does not do that, so you are stuck with old C++ way of converting a const_iterator to an iterator:

// tree is your ptree, my_const_iter a ptree::const_iterator
ptree::iterator i = tree.begin();
advance (i, std::distance<ConstIter>(i,my_const_iter));


来源:https://stackoverflow.com/questions/21427518/property-tree-put-erase-with-const-iterator-or-how-to-convert-const-iterator-to

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!