diff --git a/include/osmium/osm/node_ref.hpp b/include/osmium/osm/node_ref.hpp index 0b33c3ab..e07dc261 100644 --- a/include/osmium/osm/node_ref.hpp +++ b/include/osmium/osm/node_ref.hpp @@ -39,6 +39,7 @@ DEALINGS IN THE SOFTWARE. #include #include +#include #include namespace osmium { @@ -234,4 +235,25 @@ namespace osmium { } // namespace osmium +namespace std { + +// This pragma is a workaround for a bug in an old libc implementation +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wmismatched-tags" +#endif + template <> + struct hash { + using argument_type = osmium::NodeRef; + using result_type = size_t; + size_t operator()(const osmium::NodeRef& nr) const noexcept { + return hash{}(nr.ref()); + } + }; +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +} // namespace std + #endif // OSMIUM_OSM_NODE_REF_HPP diff --git a/test/t/osm/test_node_ref.cpp b/test/t/osm/test_node_ref.cpp index a9db8d33..6d1de3c2 100644 --- a/test/t/osm/test_node_ref.cpp +++ b/test/t/osm/test_node_ref.cpp @@ -1,5 +1,8 @@ #include "catch.hpp" +#include +#include + #include #include #include @@ -16,7 +19,7 @@ TEST_CASE("Construct a NodeRef with an id") { REQUIRE(node_ref.ref() == 7); } -TEST_CASE("Equality comparison fo NodeRefs") { +TEST_CASE("Equality comparison of NodeRefs") { const osmium::NodeRef node_ref1{7, {1.2, 3.4}}; const osmium::NodeRef node_ref2{7, {1.4, 3.1}}; const osmium::NodeRef node_ref3{9, {1.2, 3.4}}; @@ -27,6 +30,31 @@ TEST_CASE("Equality comparison fo NodeRefs") { REQUIRE( osmium::location_equal()(node_ref1, node_ref3)); } +TEST_CASE("Hash of NodeRefs") { + const osmium::NodeRef node_ref1{7, {1.2, 3.4}}; + const osmium::NodeRef node_ref2{7, {1.4, 3.1}}; + const osmium::NodeRef node_ref3{9, {1.2, 3.4}}; + + const std::hash hasher; + + SECTION("Equal NodeRefs have equal hashes") { + REQUIRE(hasher(node_ref1) == hasher(node_ref2)); + } + + SECTION("Different ref yields different hash") { + REQUIRE(hasher(node_ref1) != hasher(node_ref3)); + } + + SECTION("Hash is usable in unordered containers") { + std::unordered_set set; + set.insert(node_ref1); + set.insert(node_ref2); + REQUIRE(set.size() == 1); + set.insert(node_ref3); + REQUIRE(set.size() == 2); + } +} + TEST_CASE("Set location on a NodeRef") { osmium::NodeRef node_ref{7}; REQUIRE_FALSE(node_ref.location().valid());