Skip to content

Commit 9cef152

Browse files
committed
Implement std::hash for beman::optional
A std::hash implementation for optional, the hash of the underlying value, or 0 for disengaged.
1 parent df0a6d0 commit 9cef152

File tree

2 files changed

+32
-0
lines changed

2 files changed

+32
-0
lines changed

include/Beman/Optional26/optional.hpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1147,4 +1147,21 @@ class optional<T&> {
11471147

11481148
} // namespace beman::optional26
11491149

1150+
namespace std {
1151+
template <typename T>
1152+
requires requires(T a) {
1153+
{ std::hash<remove_const_t<T>>{}(a) } -> std::convertible_to<std::size_t>;
1154+
}
1155+
struct hash<beman::optional26::optional<T>> {
1156+
static_assert(!is_reference_v<T>, "hash is not enabled for reference types");
1157+
size_t operator()(const beman::optional26::optional<T>& o) const
1158+
noexcept(noexcept(hash<remove_const_t<T>>{}(*o))) {
1159+
if (o) {
1160+
return std::hash<std::remove_const_t<T>>{}(*o);
1161+
} else {
1162+
return 0;
1163+
}
1164+
}
1165+
};
1166+
} // namespace std
11501167
#endif // BEMAN_OPTIONAL26_OPTIONAL_HPP

src/Beman/Optional26/tests/optional.t.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,21 @@ TEST(OptionalTest, RangeTest) {
596596
}
597597
}
598598

599+
TEST(OptionalTest, HashTest) {
600+
beman::optional26::optional<int> o1 = beman::optional26::nullopt;
601+
beman::optional26::optional<int> o2 = beman::optional26::nullopt;
602+
beman::optional26::optional<int> o3 = 42;
603+
beman::optional26::optional<int> o4 = 42;
604+
605+
auto h1 = std::hash<beman::optional26::optional<int>>{}(o1);
606+
auto h2 = std::hash<beman::optional26::optional<int>>{}(o2);
607+
auto h3 = std::hash<beman::optional26::optional<int>>{}(o3);
608+
auto h4 = std::hash<beman::optional26::optional<int>>{}(o4);
609+
610+
EXPECT_EQ(h1, h2);
611+
EXPECT_EQ(h3, h4);
612+
}
613+
599614
TEST(ViewMaybeTest, Constructors) {
600615
std::ranges::single_view<std::optional<int>> s;
601616
std::ranges::single_view<std::optional<int>> s2{s};

0 commit comments

Comments
 (0)