C++: boost ptree remove children: 没有匹配函数
C++: boost ptree remove children: no matching function
为了删除 boost 属性 树的子节点,我在 erase
函数中使用了直接节点,这导致了
error: no matching function for call to
‘boost::property_tree::basic_ptree<std::__cxx11::basic_string<char>,
std::__cxx11::basic_string<char> >::erase(std::pair<const
std::__cxx11::basic_string<char>,
boost::property_tree::basic_ptree<std::__cxx11::basic_string<char>,
std::__cxx11::basic_string<char> > >&)’
在
pt0.erase(pt_child);
代码的正确形式是什么?
#include <iostream>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
using namespace boost::property_tree;
void print(const ptree &p)
{
json_parser::write_json(std::cout, p);
}
int main()
{
ptree pt0;
for(int i=0;i<10;i++)
pt0.put_child("kid"+std::to_string(i+1),ptree());
print(pt0);
for(auto& pt_child : pt0)
pt0.erase(pt_child);
print(pt0);
return 0;
}
根据 docs,您只能通过 key_type
或 iterator
.erase
,但您正试图通过 value_type
完成。
你可以做任何一个
for(auto& [key, data]: pt0)
pt0.erase(key);
或显式循环迭代器:
for(auto it = pt0.begin(); it != pt0.end(); ++it)
pt0.erase(it);
但是既然你要删除所有 children,更好的方法是只
pt0.clear();
你可以做 this:ptree.get_child("path.to").erase("child");请注意,这将删除路径 "path.to" 及其子节点中名为 "child" 的所有节点。
不幸的是,ptree
api 没有像 get_child
那样与 property_tree::path
一起工作的 remove_child
方法。不过,这里有一个小方法可以做到这一点。重要的部分是您可以使用点符号来指定要删除的任何 subchild 。此外,此实现仅删除单个 child.
#include <boost/property_tree/ptree.hpp>
#include <boost/algorithm/string.hpp>
// TODO: this should support boost::property_tree::path
// like get_child does to make it obvious that it supports
// the path separator notation for specifying sub children
bool remove_child(boost::property_tree::ptree& pt, const std::string& path) {
// split up the path into each sub part
std::vector<std::string> path_parts;
boost::split(path_parts, path, boost::is_any_of("."));
// check each part of the path
auto* root = &pt;
for (const auto& part : path_parts) {
// if we dont have this sub child bail
auto found = root->find(part);
if (found == root->not_found())
return false;
// if this was the last one to look for remove it
if (&part == &path_parts.back()) {
root->erase(root->to_iterator(found));
}// next sub child
else {
root = &found->second;
}
}
// made it to the last sub child without bailing on not found
return true;
}
为了删除 boost 属性 树的子节点,我在 erase
函数中使用了直接节点,这导致了
error: no matching function for call to
‘boost::property_tree::basic_ptree<std::__cxx11::basic_string<char>,
std::__cxx11::basic_string<char> >::erase(std::pair<const
std::__cxx11::basic_string<char>,
boost::property_tree::basic_ptree<std::__cxx11::basic_string<char>,
std::__cxx11::basic_string<char> > >&)’
在
pt0.erase(pt_child);
代码的正确形式是什么?
#include <iostream>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
using namespace boost::property_tree;
void print(const ptree &p)
{
json_parser::write_json(std::cout, p);
}
int main()
{
ptree pt0;
for(int i=0;i<10;i++)
pt0.put_child("kid"+std::to_string(i+1),ptree());
print(pt0);
for(auto& pt_child : pt0)
pt0.erase(pt_child);
print(pt0);
return 0;
}
根据 docs,您只能通过 key_type
或 iterator
.erase
,但您正试图通过 value_type
完成。
你可以做任何一个
for(auto& [key, data]: pt0)
pt0.erase(key);
或显式循环迭代器:
for(auto it = pt0.begin(); it != pt0.end(); ++it)
pt0.erase(it);
但是既然你要删除所有 children,更好的方法是只
pt0.clear();
你可以做 this:ptree.get_child("path.to").erase("child");请注意,这将删除路径 "path.to" 及其子节点中名为 "child" 的所有节点。
不幸的是,ptree
api 没有像 get_child
那样与 property_tree::path
一起工作的 remove_child
方法。不过,这里有一个小方法可以做到这一点。重要的部分是您可以使用点符号来指定要删除的任何 subchild 。此外,此实现仅删除单个 child.
#include <boost/property_tree/ptree.hpp>
#include <boost/algorithm/string.hpp>
// TODO: this should support boost::property_tree::path
// like get_child does to make it obvious that it supports
// the path separator notation for specifying sub children
bool remove_child(boost::property_tree::ptree& pt, const std::string& path) {
// split up the path into each sub part
std::vector<std::string> path_parts;
boost::split(path_parts, path, boost::is_any_of("."));
// check each part of the path
auto* root = &pt;
for (const auto& part : path_parts) {
// if we dont have this sub child bail
auto found = root->find(part);
if (found == root->not_found())
return false;
// if this was the last one to look for remove it
if (&part == &path_parts.back()) {
root->erase(root->to_iterator(found));
}// next sub child
else {
root = &found->second;
}
}
// made it to the last sub child without bailing on not found
return true;
}