【问题标题】:C++: boost ptree remove children: no matching functionC++:boost ptree remove children:没有匹配的函数
【发布时间】:2017-12-28 10:35:24
【问题描述】:

为了移除 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;
}

【问题讨论】:

  • 发布整个错误信息。
  • @yurikilochek,好的。
  • 题外话:你可以write_json(std::cout, p) 不需要通过stringstream。
  • @yurikilochek,已更新。谢谢。

标签: c++ c++11 boost boost-propertytree ptree


【解决方案1】:

你可以这样做:ptree.get_child("path.to").erase("child");请注意,这会删除路径“path.to”及其子子级中名为“child”的所有节点。

【讨论】:

    【解决方案2】:

    不幸的是,ptree api 没有 remove_child 方法,它可以与 property_tree::path 一起使用,就像 get_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;
    }
    

    【讨论】:

      【解决方案3】:

      根据docs,您只能通过key_typeiterator 进行.erase,但您正试图通过value_type 进行操作。

      你可以做任何一个做

      for(auto& [key, data]: pt0)
          pt0.erase(key);
      

      或显式循环迭代器:

      for(auto it = pt0.begin(); it != pt0.end(); ++it)
          pt0.erase(it);
      

      但既然你无论如何都要删除所有孩子,更好的方法是只

      pt0.clear();
      

      【讨论】:

      • @ar2015 你为什么不read the docs自己呢?
      • 错误:'[' token ` for(auto& [key, data]: pt0)` 之前的预期 unqualified-id,错误:'key' 未在此范围内声明,错误:'data'未在此范围内声明
      • @ar2015 这是 c++17 语法,在此之前你可以这样做 for(auto&amp; pt_child: pt0) pt0.erase(pt_child.first);
      • 两个循环在修改过程中都会修改容器。那是UB。您必须安全地编写循环,例如:for(auto it = pt0.begin(); it != pt0.end();) { it = pt0.erase(it); }.
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-11
      • 1970-01-01
      • 2021-12-26
      • 2012-07-20
      • 2017-12-28
      相关资源
      最近更新 更多