c++ - 如何返回 boost::property_tree 的叶节点

标签 c++ boost boost-propertytree

我有一个属性树,其中所有数据都存储在其叶节点中。然而,树具有复杂的结构。我现在想做的是:

  1. 获取树的所有(且仅)叶节点,因为它们包含数据并且
  2. 记忆通向各自叶节点的路径

最终,我想接收所有(且仅是)叶节点的键/值对,其中键包含节点的完整路径,值包含节点的值。

我的问题是:

  1. 有没有比递归遍历整个树更方便的方法,存储各自的路径并读出没有子节点的值(即“get_leaves() “函数)?
  2. 如果我有一些指向给定树的子树(ptree变量,迭代器,等等......)的指针,是否有一种方法可以轻松确定相对路径树内的子树?

最佳答案

我只是编写一些辅助函数。他们真的没那么难。这是一个完全通用的树访问函数,可以选择使用谓词:

template <typename Tree, typename F, typename Pred/* = bool(*)(Tree const&)*/, typename PathType = std::string>
void visit_if(Tree& tree, F const& f, Pred const& p, PathType const& path = PathType())
{
    if (p(tree))
        f(path, tree);

    for(auto& child : tree)
        if (path.empty())
            visit_if(child.second, f, p, child.first);
        else
            visit_if(child.second, f, p, path + "." + child.first);
}

template <typename Tree, typename F, typename PathType = std::string>
void visit(Tree& tree, F const& f, PathType const& path = PathType())
{
    visit_if(tree, f, [](Tree const&){ return true; }, path);
}

您可以将其与谓词一起使用,例如

#include <boost/property_tree/ptree.hpp>

bool is_leaf(boost::property_tree::ptree const& pt) {
    return pt.empty();
}

这是一个简单的演示:

Live On Coliru

#include <iostream>
int main()
{
    using boost::property_tree::ptree;
    auto process = [](ptree::path_type const& path, ptree const& node) {
            std::cout << "leave node at '" << path.dump() << "' has value '" << node.get_value("") << "'\n";
        };

    ptree pt;
    pt.put("some.deeply.nested.values", "just");
    pt.put("for.the.sake.of.demonstration", 42);

    visit_if(pt, process, is_leaf);
}

打印:

leave node at 'some.deeply.nested.values' has value 'just'
leave node at 'for.the.sake.of.demonstration' has value '42'

更新

刚刚注意到问题的后半部分。以下是使用同一访问者执行此操作的方法:

template <typename Tree>
boost::optional<std::string> path_of_optional(Tree const& tree, Tree const& target) {
    boost::optional<std::string> result;

    visit(tree, [&](std::string const& path, Tree const& current) { if (&target == &current) result = path; });

    return result;
}

template <typename Tree>
std::string path_of(Tree const& tree, Tree const& target) {
    auto r = path_of_optional(tree, target);
    if (!r) throw std::range_error("path_of");
    return *r;
}

还有一个演示 Live On Coliru

std::cout << "Path from node: " << path_of(pt, pt.get_child("for.the.sake")) << "\n";

关于c++ - 如何返回 boost::property_tree 的叶节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30571536/

相关文章:

c++ - 将 C++ 模板参数限制为相同值类型的容器

C++ 标准库方法删除列表中满足条件的一对项目中的一个

c++ - 如何使用boost获取前一天的日期?

c++ - 通过 boost 属性树发出 YAML 迭代(递归)

c++ - 使用 boost::asio::spawn 生成的 asio 处理程序中的 boost::property_tree::read_xml 段错误

c++ - 当值部分不存在时使用 Boost Property Tree 读取 INI 文件

c++ - 包装数组的类的转换与下标运算符重载

c++ - Boost::Thread/C++11 std::thread,想要在条件下唤醒工作线程

c++ - Boost图库: Get edge_descriptor or access edge by index of type int

c++ - 让主线程等到所有其他 Qthread 完成