Make nodes hashable

Implement a specialization of `std::hash<YAML::Node>` so that nodes can
be used in unordered associative containers.
This commit is contained in:
Fredrik Appelros 2018-06-07 17:37:53 +02:00
parent 0122697561
commit 67ae33d908
5 changed files with 39 additions and 0 deletions

View File

@ -18,6 +18,8 @@ namespace YAML {
namespace detail {
class node {
public:
friend struct std::hash<node>;
node() : m_pRef(new node_ref), m_dependencies{} {}
node(const node&) = delete;
node& operator=(const node&) = delete;

View File

@ -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<YAML::detail::node> {
size_t operator()(const YAML::detail::node& key) const noexcept {
return hash<YAML::detail::shared_node_ref>()(key.m_pRef);
}
};
template <>
struct hash<YAML::Node> {
size_t operator()(const YAML::Node& key) const noexcept {
return hash<YAML::detail::node>()(*key.m_pNode);
}
};
} // namespace std
#endif // NODE_HASH_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@ -38,6 +38,7 @@ class YAML_CPP_API Node {
friend class detail::iterator_base;
template <typename T, typename S>
friend struct as_if;
friend struct std::hash<Node>;
typedef YAML::iterator iterator;
typedef YAML::const_iterator const_iterator;

View File

@ -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

View File

@ -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<YAML::Node> 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) {