diff --git a/include/yaml-cpp/node/detail/node.h b/include/yaml-cpp/node/detail/node.h index a2cc52b76..48fb5717f 100644 --- a/include/yaml-cpp/node/detail/node.h +++ b/include/yaml-cpp/node/detail/node.h @@ -18,6 +18,8 @@ namespace YAML { namespace detail { class node { public: + friend struct std::hash; + node() : m_pRef(new node_ref), m_dependencies{} {} node(const node&) = delete; node& operator=(const node&) = delete; diff --git a/include/yaml-cpp/node/hash.h b/include/yaml-cpp/node/hash.h new file mode 100644 index 000000000..8d5f9b09c --- /dev/null +++ b/include/yaml-cpp/node/hash.h @@ -0,0 +1,23 @@ +#ifndef NODE_HASH_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define NODE_HASH_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#include "yaml-cpp/node/detail/node.h" +#include "yaml-cpp/node/node.h" + +namespace std { +template <> +struct hash { + size_t operator()(const YAML::detail::node& key) const noexcept { + return hash()(key.m_pRef); + } +}; + +template <> +struct hash { + size_t operator()(const YAML::Node& key) const noexcept { + return hash()(*key.m_pNode); + } +}; +} // namespace std + +#endif // NODE_HASH_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/include/yaml-cpp/node/node.h b/include/yaml-cpp/node/node.h index 49af58e5c..e813cf7cf 100644 --- a/include/yaml-cpp/node/node.h +++ b/include/yaml-cpp/node/node.h @@ -38,6 +38,7 @@ class YAML_CPP_API Node { friend class detail::iterator_base; template friend struct as_if; + friend struct std::hash; typedef YAML::iterator iterator; typedef YAML::const_iterator const_iterator; diff --git a/include/yaml-cpp/yaml.h b/include/yaml-cpp/yaml.h index 7f515efb9..6a754ec4c 100644 --- a/include/yaml-cpp/yaml.h +++ b/include/yaml-cpp/yaml.h @@ -20,5 +20,6 @@ #include "yaml-cpp/node/detail/impl.h" #include "yaml-cpp/node/parse.h" #include "yaml-cpp/node/emit.h" +#include "yaml-cpp/node/hash.h" #endif // YAML_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/test/node/node_test.cpp b/test/node/node_test.cpp index 18234dbde..47df6cf9d 100644 --- a/test/node/node_test.cpp +++ b/test/node/node_test.cpp @@ -3,6 +3,7 @@ #include "yaml-cpp/node/convert.h" #include "yaml-cpp/node/detail/impl.h" #include "yaml-cpp/node/emit.h" +#include "yaml-cpp/node/hash.h" #include "yaml-cpp/node/impl.h" #include "yaml-cpp/node/iterator.h" @@ -437,6 +438,17 @@ TEST(NodeTest, AccessNonexistentKeyOnConstNode) { ASSERT_FALSE(other["5"]); } +TEST(NodeTest, NodeIsHashable) { + YAML::Node node1(YAML::NodeType::value::Null); + YAML::Node node2(YAML::NodeType::value::Null); + YAML::Node node3 = node1; + std::hash hash_func; + auto node1_digest = hash_func(node1); + ASSERT_EQ(hash_func(node1), node1_digest); + ASSERT_NE(hash_func(node2), node1_digest); + ASSERT_EQ(hash_func(node3), node1_digest); +} + class NodeEmitterTest : public ::testing::Test { protected: void ExpectOutput(const std::string& output, const Node& node) {