This is an automated email from the ASF dual-hosted git repository.
astitcher pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/qpid-proton.git
The following commit(s) were added to refs/heads/main by this push:
new 86281a4a7 PROTON-2888: [C++] Added std:hash specializations
86281a4a7 is described below
commit 86281a4a7c91bccde616e0d3524194f79a509a56
Author: Andrew Stitcher <[email protected]>
AuthorDate: Tue Apr 8 21:43:16 2025 -0400
PROTON-2888: [C++] Added std:hash specializations
This allows proton::uuid, proton::binary and proton::message_id to be
used as keys in unordered std datastructures.
Now we can use proton::binary as the key for std::unordered_map etc.
---
cpp/include/proton/binary.hpp | 8 ++++++++
cpp/include/proton/message_id.hpp | 19 +++++++++++++++++++
cpp/include/proton/uuid.hpp | 8 ++++++++
cpp/src/scalar_test.cpp | 29 +++++++++++++++++++++++++++++
cpp/src/tracing_opentelemetry.cpp | 8 --------
5 files changed, 64 insertions(+), 8 deletions(-)
diff --git a/cpp/include/proton/binary.hpp b/cpp/include/proton/binary.hpp
index f7396f6b3..b01e40236 100644
--- a/cpp/include/proton/binary.hpp
+++ b/cpp/include/proton/binary.hpp
@@ -59,4 +59,12 @@ PN_CPP_EXTERN std::ostream& operator<<(std::ostream&, const
binary&);
} // proton
+/// Specialize std::hash so we can use proton::binary as a key for unordered
datastructures
+template <> struct std::hash<proton::binary> {
+ std::size_t operator()(const proton::binary& k) const {
+ std::string s{k};
+ return std::hash<std::string>{}(s);
+ }
+};
+
#endif // PROTON_BINARY_HPP
diff --git a/cpp/include/proton/message_id.hpp
b/cpp/include/proton/message_id.hpp
index 2edcc2308..aacd35cdf 100644
--- a/cpp/include/proton/message_id.hpp
+++ b/cpp/include/proton/message_id.hpp
@@ -92,4 +92,23 @@ template<class T> T coerce(const message_id& x) { return
internal::coerce<T>(x);
} // proton
+/// Specialize std::hash so we can use proton::message_id as a key for
unordered datastructures
+template <> struct std::hash<proton::message_id> {
+ std::size_t operator()(const proton::message_id& s) const {
+ std::size_t h;
+ auto type = s.type();
+ switch(type) {
+ case proton::ULONG: h =
std::hash<uint64_t>{}(proton::internal::get<uint64_t>(s)); break;
+ case proton::UUID: h =
std::hash<proton::uuid>{}(proton::internal::get<proton::uuid>(s)); break;
+ case proton::BINARY: h =
std::hash<proton::binary>{}(proton::internal::get<proton::binary>(s)); break;
+ case proton::STRING: h =
std::hash<std::string>{}(proton::internal::get<std::string>(s)); break;
+ default: throw proton::conversion_error("invalid message_id type
"+type_name(s.type()));
+ }
+ auto type_hash = std::hash<proton::type_id>{}(type);
+ // Combine the two hashes - see https://stackoverflow.com/a/5889238
+ return h ^ (type_hash + 0x9e3779b9 + (h << 6) + (h >> 2));
+}
+
+};
+
#endif // PROTON_MESSAGE_ID_HPP
diff --git a/cpp/include/proton/uuid.hpp b/cpp/include/proton/uuid.hpp
index a48712651..ce59a0db8 100644
--- a/cpp/include/proton/uuid.hpp
+++ b/cpp/include/proton/uuid.hpp
@@ -66,4 +66,12 @@ inline std::string to_string(const uuid& u) { return
u.str(); }
} // proton
+/// Specialize std::hash so we can use proton::uuid as a key for unordered
datastructures
+template <> struct std::hash<proton::uuid> {
+ std::size_t operator()(const proton::uuid& k) const {
+ std::string s{k.begin(), k.end()};
+ return std::hash<std::string>{}(s);
+ };
+};
+
#endif // PROTON_UUID_HPP
diff --git a/cpp/src/scalar_test.cpp b/cpp/src/scalar_test.cpp
index 54be0b974..9fcb53df0 100644
--- a/cpp/src/scalar_test.cpp
+++ b/cpp/src/scalar_test.cpp
@@ -56,6 +56,34 @@ void annotation_key_test() {
ASSERT_EQUAL(scalar(symbol("foo")), annotation_key("foo"));
}
+void hash_test() {
+ std::hash<binary> binary_hash;
+ ASSERT_EQUAL(binary_hash(binary("foo")), binary_hash(binary("foo")));
+ ASSERT(binary_hash(binary("foo")) != binary_hash(binary("bar")));
+
+ std::hash<uuid> uuid_hash;
+ auto u1 = uuid::random();
+ auto u2 = uuid::random();
+ ASSERT_EQUAL(uuid_hash(u1), uuid_hash(u1));
+ ASSERT(uuid_hash(u1) != uuid_hash(u2));
+
+ std::hash<message_id> message_id_hash;
+ ASSERT_EQUAL(message_id_hash(message_id("foo")),
message_id_hash(message_id("foo")));
+ ASSERT(message_id_hash(message_id("foo")) !=
message_id_hash(message_id("bar")));
+ ASSERT_EQUAL(message_id_hash(message_id(23)),
message_id_hash(message_id(23)));
+ ASSERT(message_id_hash(message_id(23)) != message_id_hash(message_id(24)));
+ ASSERT_EQUAL(message_id_hash(message_id(u1)),
message_id_hash(message_id(u1)));
+ ASSERT(message_id_hash(message_id(u1)) != message_id_hash(message_id(u2)));
+ ASSERT_EQUAL(message_id_hash(message_id(binary("foo"))),
message_id_hash(message_id(binary("foo"))));
+ ASSERT(message_id_hash(message_id(binary("foo"))) !=
message_id_hash(message_id(binary("bar"))));
+
+ binary b1{u1.begin(), u1.end()};
+ ASSERT(message_id_hash(message_id(b1)) != message_id_hash(message_id(u1)));
+ binary b23{23};
+ ASSERT(message_id_hash(message_id(b23)) !=
message_id_hash(message_id(23)));
+
+}
+
template <class T> T make(const char c) { T x; std::fill(x.begin(), x.end(),
c); return x; }
}
@@ -67,5 +95,6 @@ int main(int, char**) {
RUN_TEST(failed, encode_decode_test());
RUN_TEST(failed, message_id_test());
RUN_TEST(failed, annotation_key_test());
+ RUN_TEST(failed, hash_test());
return failed;
}
diff --git a/cpp/src/tracing_opentelemetry.cpp
b/cpp/src/tracing_opentelemetry.cpp
index e453f8381..a571fe8cb 100644
--- a/cpp/src/tracing_opentelemetry.cpp
+++ b/cpp/src/tracing_opentelemetry.cpp
@@ -55,14 +55,6 @@
#include <string>
#include <unordered_map>
-// Custom specialization of std::hash injected in namespace std for
proton::binary as a key in tag_span i.e. an unordered_map.
-template <> struct std::hash<proton::binary> {
- std::size_t operator()(const proton::binary& k) const {
- std::string s(k[0], k.size());
- return std::hash<std::string>{}(s);
- }
-};
-
namespace proton
{
namespace nostd = opentelemetry::nostd;
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]