diff --git a/include/yaml-cpp/node/impl.h b/include/yaml-cpp/node/impl.h index 20c487a68..fdca08422 100644 --- a/include/yaml-cpp/node/impl.h +++ b/include/yaml-cpp/node/impl.h @@ -239,11 +239,12 @@ inline void Node::Assign(char* rhs) { } inline Node& Node::operator=(const Node& rhs) { - if (!m_isValid || !rhs.m_isValid) - throw InvalidNode(); - if (is(rhs)) - return *this; - AssignNode(rhs); + AssignData(rhs); + return *this; +} + +inline Node& Node::operator=(const NodeAlias& rhs) { + AssignNode(rhs.m_node); return *this; } diff --git a/include/yaml-cpp/node/node.h b/include/yaml-cpp/node/node.h index 1ded7d27b..5d82368fc 100644 --- a/include/yaml-cpp/node/node.h +++ b/include/yaml-cpp/node/node.h @@ -26,6 +26,7 @@ struct iterator_value; } // namespace YAML namespace YAML { +class YAML_CPP_API NodeAlias; class YAML_CPP_API Node { public: friend class NodeBuilder; @@ -81,6 +82,7 @@ class YAML_CPP_API Node { template Node& operator=(const T& rhs); Node& operator=(const Node& rhs); + Node& operator=(const NodeAlias& rhs); void reset(const Node& rhs = Node()); // size/iterator @@ -134,6 +136,14 @@ class YAML_CPP_API Node { mutable detail::node* m_pNode; }; +class NodeAlias { + friend class Node; +public: + NodeAlias(const Node& node) : m_node(node) {} +private: + const Node& m_node; +}; + YAML_CPP_API bool operator==(const Node& lhs, const Node& rhs); YAML_CPP_API Node Clone(const Node& node); diff --git a/test/integration/handler_test.cpp b/test/integration/handler_test.cpp index 601146071..da9a10c1a 100644 --- a/test/integration/handler_test.cpp +++ b/test/integration/handler_test.cpp @@ -1,5 +1,4 @@ #include "handler_test.h" -#include "specexamples.h" // IWYU pragma: keep #include "yaml-cpp/yaml.h" // IWYU pragma: keep #include "gmock/gmock.h" diff --git a/test/integration/load_node_test.cpp b/test/integration/load_node_test.cpp index 02bb8fe58..4a782963b 100644 --- a/test/integration/load_node_test.cpp +++ b/test/integration/load_node_test.cpp @@ -78,6 +78,22 @@ TEST(LoadNodeTest, IterateMap) { EXPECT_EQ(3, i); } +TEST(LoadNodeTest, AliasMultipleAssign) { + Node doc = Load("{A: &DEFAULT {str: string, int: 42, float: 3.1415}, B: *DEFAULT}"); + + for (YAML::const_iterator it = doc.begin(); it != doc.end(); ++it) { + SCOPED_TRACE("group " + it->first.as()); + Node value; + + value = it->second["str"]; + EXPECT_STREQ(value.as().c_str(), "string"); + value = it->second["float"]; + EXPECT_EQ(value.as(), 3.1415f); + value = it->second["int"]; + EXPECT_EQ(value.as(), 42); + } +} + #ifdef BOOST_FOREACH TEST(LoadNodeTest, ForEach) { Node node = Load("[1, 3, 5, 7]"); diff --git a/test/node/node_test.cpp b/test/node/node_test.cpp index 485ad09e1..e6f105446 100644 --- a/test/node/node_test.cpp +++ b/test/node/node_test.cpp @@ -254,7 +254,7 @@ TEST(NodeTest, StdPair) { TEST(NodeTest, SimpleAlias) { Node node; node["foo"] = "value"; - node["bar"] = node["foo"]; + node["bar"] = NodeAlias(node["foo"]); EXPECT_EQ("value", node["foo"].as()); EXPECT_EQ("value", node["bar"].as()); EXPECT_EQ(node["bar"], node["foo"]); @@ -274,7 +274,7 @@ TEST(NodeTest, AliasAsKey) { TEST(NodeTest, SelfReferenceSequence) { Node node; - node[0] = node; + node[0] = NodeAlias(node); EXPECT_TRUE(node.IsSequence()); EXPECT_EQ(1, node.size()); EXPECT_EQ(node, node[0]); @@ -284,7 +284,7 @@ TEST(NodeTest, SelfReferenceSequence) { TEST(NodeTest, ValueSelfReferenceMap) { Node node; - node["key"] = node; + node["key"] = NodeAlias(node); EXPECT_TRUE(node.IsMap()); EXPECT_EQ(1, node.size()); EXPECT_EQ(node, node["key"]); @@ -302,7 +302,7 @@ TEST(NodeTest, KeySelfReferenceMap) { TEST(NodeTest, SelfReferenceMap) { Node node; - node[node] = node; + node[node] = NodeAlias(node); EXPECT_TRUE(node.IsMap()); EXPECT_EQ(1, node.size()); EXPECT_EQ(node, node[node]); @@ -322,7 +322,7 @@ TEST(NodeTest, TempMapVariable) { TEST(NodeTest, TempMapVariableAlias) { Node node; Node tmp = node["key"]; - tmp = node["other"]; + tmp = NodeAlias(node["other"]); node["other"] = "value"; EXPECT_TRUE(node.IsMap()); EXPECT_EQ(2, node.size());