gpt4 book ai didi

c++ - 递归添加子树以 boost 属性树

转载 作者:行者123 更新时间:2023-11-30 05:00:23 28 4
gpt4 key购买 nike

我想用 C++ 编写一个参数服务器,我可以在其中递归地将参数树转储到属性树中,然后将其写入 JSON 文件。转储函数如下所示:

 void Params::dump(string filename) {
// Create a root
pt::ptree root;

// Fill the root with parameters
mapToPt(curParams, root);

// Write to cout
pt::write_json(cout, root);
}

mapToPt 应该递归地遍历我的参数服务器的层次结构,并在这样做时填充属性树:

  void Params::mapToPt(boost::shared_ptr<Params> curParams, pt::ptree &root) {
// Fill current root with parameters from curParams ParameterMap
map<string, boost::shared_ptr<Param> >::iterator it;
for ( it = curParams->getParamMap().begin(); it != curParams-getParamMap().end(); it++ ) {
root.put(it->first, it->second->getValue());
cout << "Add Parameter: \n";
cout << "Parameter name: " << it->first << "\n";
cout << "Parameter value: " << it->second->getValue() << "\n";
}

// Recursively go through all children to do the same to them
if(curParams->hasChildren()) { //ERROR LINE
map<string, boost::shared_ptr<Params> >::iterator it;
for ( it = curParams->getChildren().begin(); it != curParams-getChildren().end(); it++ ) {
pt::ptree new_tree;
root.add_child(it->second->getName(), new_tree);
cout << "Add Child: \n";
cout << "Child name: " << it->second->getName() << "\n";
mapToPt(it->second, new_tree);
}
}
}

我的问题是,一旦我进入递归,错误就出现在随机行上,而这不可能是错误的原因。 “basic_string::_M_construct null 无效”是错误消息。我相信我可能会访问已删除的内容,这可能是由于我遍历属性树子项的方式所致。我的做法是错误的还是有其他方法?

谢谢。

最佳答案

mapToPt 还需要一个指向 Params 实例的指针时,为什么它是一个成员?

哎呀,有点困惑。

在设计层面,您的 Params 类型看起来无法决定它是否是叶节点。此外,它还受到“准类”设计的影响, setter/getter 基本上保证没有类不变性。在这种情况下,最好只使用一个包含成员字段的结构。

Note, if you fail to return by reference from getParamMap() and getChildren() then you already have Undefined Behaviour in both loops, because the iterators then point into non-existent copies of containers.

You should check this. Also, see my working demo below

在实现层面,这会给您带来问题:

        pt::ptree new_tree;
root.add_child(it->second->getName(), new_tree);

add_child 插入 new_tree 的拷贝。以后对 new_tree 的任何修改都无效。相反,写:

        pt::ptree& new_tree = root.add_child(it->second->getName(), {});

在这里,new_tree 成为对实际添加的树的引用

尝试修复

风格仍然低于我的预期。就我个人而言,我会仔细检查这段代码中 shared_ptr 的使用。

但这可能会对您有所帮助:

Live On Coliru

#include <boost/make_shared.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <iostream>
#include <map>

namespace pt = boost::property_tree;

struct Param {
std::string getValue() const { return "42"; }
};

struct Params {
using ParamMap = std::map<std::string, boost::shared_ptr<Param> >;
using Children = std::map<std::string, boost::shared_ptr<Params> >;

Params(std::string name = "") : _name(name) {}

std::string getName() const { return _name; }

ParamMap& getParamMap() { return _map; }
ParamMap const& getParamMap() const { return _map; }

bool hasChildren() const { return !_children.empty(); }
Children& getChildren() { return _children; }
Children const& getChildren() const { return _children; }

static void mapToPt(boost::shared_ptr<Params> curParams, pt::ptree &root);

private:
std::string _name;
ParamMap _map;
Children _children;
};

void Params::mapToPt(boost::shared_ptr<Params> curParams, pt::ptree &root) {
// Fill current root with parameters from curParams ParameterMap
std::map<std::string, boost::shared_ptr<Param> >::iterator it;
for (it = curParams->getParamMap().begin(); it != curParams->getParamMap().end(); it++) {
root.put(it->first, it->second->getValue());
//std::cout << "Add Parameter: \n";
//std::cout << "Parameter name: " << it->first << "\n";
//std::cout << "Parameter value: " << it->second->getValue() << "\n";
}

// Recursively go through all children to do the same to them
if (curParams->hasChildren()) {
for (auto it = curParams->getChildren().begin(); it != curParams->getChildren().end(); it++) {
pt::ptree& new_tree = root.add_child(it->second->getName(), {});
//std::cout << "Add Child: \n";
//std::cout << "Child name: " << it->second->getName() << "\n";
mapToPt(it->second, new_tree);
}
}
}

int main() {
auto a = boost::make_shared<Params>("rootparams");

a->getParamMap().emplace("one", boost::make_shared<Param>());
a->getParamMap().emplace("two", boost::make_shared<Param>());
a->getParamMap().emplace("three", boost::make_shared<Param>());

a->getChildren().emplace("child1", boost::make_shared<Params>("child1-name"))
.first->second->getParamMap().emplace("four", boost::make_shared<Param>());

a->getChildren().emplace("child2", boost::make_shared<Params>("child2-name"))
.first->second->getParamMap().emplace("five", boost::make_shared<Param>());

pt::ptree root;
a->mapToPt(a, root);

write_json(std::cout, root);
}

打印

{
"one": "42",
"three": "42",
"two": "42",
"child1-name": {
"four": "42"
},
"child2-name": {
"five": "42"
}
}

关于c++ - 递归添加子树以 boost 属性树,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50836911/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com