【发布时间】:2018-08-20 11:55:36
【问题描述】:
对于 .yaml,比如说
aaa:
bbb:
ccc: testOne
ddd: testTwo
目标是找到给定参数路径的值,例如aaa/bbb/ccc。当我尝试执行此操作两次时,尽管传递了一个 const YAML::Node,但父 aaa 已更改并指向我上次搜索的位置。 我理解 YAML::Nodes 只是一个浅层结构,因此我的操作显然正在改变底层数据。在不更改输入数据的情况下导航树的巧妙方法是什么?
有关详细信息,请参阅带有一些调试输出的最小示例:
std::string findNodeInYAMLTree(const YAML::Node node, const std::vector<std::string> &pathInTree)
{
std::cout << "Input root node for findNodeInYAMLTree():" << std::endl;
for (const auto& kv : node) {
std::cout << kv.first.as<std::string>() << "\n";
}
YAML::Node parentNode = node;
YAML::Node childNode = parentNode;
std::vector<std::string>::const_iterator it = pathInTree.begin();
while (it != pathInTree.end()) {
std::string childNodeName = *it;
if (!parentNode.IsDefined() || !parentNode[childNodeName]) {
std::cout << "Did not find the next tree path node <" << childNodeName << ">" << std::endl;
return "Failure";
}
childNode = parentNode[childNodeName];
parentNode = childNode;
it++;
}
return childNode.as<std::string>();
}
void testSameFctTwice()
{
YAML::Node aaa;
YAML::Node node = YAML::Load("aaa: {bbb: {ccc: testOne, ddd: testTwo}}");
std::vector<std::string> testOneStr({"aaa", "bbb","ccc"});
std::cout << findNodeInYAMLTree(node, testOneStr) << std::endl;
std::vector<std::string> testTwoStr({"aaa", "bbb", "ddd"});
std::cout << findNodeInYAMLTree(node, testTwoStr) << std::endl;
}
我使用的是system-repo的0.5.2版本,暂时将yaml-cpp更新到0.6/HEAD并没有改变。
输出将是:
Input root node for findNodeInYAMLTree():
aaa
testOne
Input root node for findNodeInYAMLTree():
ddd
ccc
Did not find the next tree path node <aaa>
Failure
所以解决方法是:
YAML::Node parentNode = YAML::Clone(node);
但我觉得这可以做得更好。
【问题讨论】:
-
大概
findNodeInYAMLTree(const YAML::Node node,应该是findNodeInYAMLTree(const YAML::Node& node,? -
也许将
parentNode和childNode更改为指针?我猜childNode = parentNode[childNodeName]是将parentNode[childNodeName]的内容复制到childNode中,对于图书馆来说不是一件很友好的事情就是这样 -
至于参考 YAML::Node &node 传递,无济于事。 YAML::Node 只不过是一个 bool 和两个指针而已。
-
我没有设法写一个指针版本,因为“取临时地址”的编译器错误。 parentNode[childNodeName] 中的 operator[ ] 在该范围内创建一个 Node()。我想这不是要走的路,因为 parentNode[childNodeName] 是唯一可以更改输入数据的操作,但在使用指针时不会被替换。谢谢@AlanBirtles