const yaml-cpp 节点多次使用时会发生变化
const yaml-cpp node changes when used multiple times
对于 .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);
但我觉得这可以做得更好。
在yaml-cpp中,operator =
分配了一个参考值。这有点不直观;请参阅 this issue 讨论问题。
而是调用 Node::reset
:
childNode.reset(parentNode[childNodeName]);
对于 .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);
但我觉得这可以做得更好。
在yaml-cpp中,operator =
分配了一个参考值。这有点不直观;请参阅 this issue 讨论问题。
而是调用 Node::reset
:
childNode.reset(parentNode[childNodeName]);