Skip to content

Commit

Permalink
reorganize hash header (again) and add hash_range (#26)
Browse files Browse the repository at this point in the history
* reorganize hash header (again) and add hash_range

* resolve circular dependency

* use hash_combine instead of hash_range

* remove no longer neccesary forward declaration

* move forward declaration header, enable hashing empty range

* make hash_value_for depends on Boost

* fix hash_combine related operations

* IWYU

* add test

* Revert "fix hash_combine related operations"

This reverts commit 1ae9e25.

* yet another fix
  • Loading branch information
yaito3014 authored Sep 6, 2024
1 parent 924ccd1 commit d1d6b59
Show file tree
Hide file tree
Showing 9 changed files with 94 additions and 63 deletions.
10 changes: 0 additions & 10 deletions include/yk/hash.hpp

This file was deleted.

8 changes: 4 additions & 4 deletions include/yk/hash/adapt.hpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#ifndef YK_UTIL_HASH_HASH_HPP
#define YK_UTIL_HASH_HASH_HPP
#ifndef YK_UTIL_HASH_ADAPT_HPP
#define YK_UTIL_HASH_ADAPT_HPP

#include "yk/hash/std.hpp"
#include "yk/hash/hash_value_for.hpp"

#define YK_PP_REQUIRE_SEMICOLON static_assert(true)

Expand Down Expand Up @@ -43,4 +43,4 @@
} /* ns */ \
YK_PP_REQUIRE_SEMICOLON

#endif // YK_UTIL_HASH_HASH_HPP
#endif // YK_UTIL_HASH_ADAPT_HPP
17 changes: 0 additions & 17 deletions include/yk/hash/boost.hpp

This file was deleted.

10 changes: 5 additions & 5 deletions include/yk/hash/hash_combine.hpp
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
#ifndef YK_UTIL_HASH_HASH_COMBINE_HPP
#define YK_UTIL_HASH_HASH_COMBINE_HPP

#include "yk/hash/std.hpp"
#include "yk/hash/hash_value_for/fwd.hpp"

#include <boost/container_hash/hash_fwd.hpp>

#include <cstddef>

namespace yk {

template <class T, class... Rest>
[[nodiscard]] constexpr std::size_t hash_combine(const T& first_arg, const Rest&... rest) noexcept /* strengthened */ {
std::size_t seed = ::yk::hash_value_for(first_arg);
(boost::hash_combine(seed, ::yk::hash_value_for(rest)), ...);
template <class... Ts>
[[nodiscard]] constexpr std::size_t hash_combine(const Ts&... xs) noexcept /* strengthened */ {
std::size_t seed = 0;
(boost::hash_combine(seed, ::yk::hash_value_for(xs)), ...);
return seed;
}

Expand Down
37 changes: 37 additions & 0 deletions include/yk/hash/hash_value_for.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#ifndef YK_HASH_HASH_VALUE_FOR_HPP
#define YK_HASH_HASH_VALUE_FOR_HPP

#include "yk/hash/range.hpp"

#include <boost/container_hash/hash_fwd.hpp>

#include <functional>

namespace yk {

template <class T>
[[nodiscard]] constexpr std::size_t std_hash_value_for(const T& x) noexcept {
return std::hash<T>{}(x);
}

template <class T>
[[nodiscard]] constexpr std::size_t boost_hash_value_for(const T& x) noexcept {
return boost::hash<T>{}(x);
}

template <class T>
[[nodiscard]] constexpr std::size_t hash_value_for(const T& x) noexcept {
if constexpr (requires(std::hash<T> hasher) { hasher(x); }) {
return std::hash<T>{}(x);
} else if constexpr (requires { hash_value(x); }) {
return hash_value(x);
} else if constexpr (requires { ::yk::hash_range(x); }) {
return ::yk::hash_range(x);
} else {
static_assert(false, "no hasher found");
}
}

} // namespace yk

#endif // YK_HASH_HASH_VALUE_FOR_HPP
13 changes: 13 additions & 0 deletions include/yk/hash/hash_value_for/fwd.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#ifndef YK_HASH_HASH_VALUE_FOR_FWD_HPP
#define YK_HASH_HASH_VALUE_FOR_FWD_HPP

#include <cstddef>

namespace yk {

template <class T>
[[nodiscard]] constexpr std::size_t hash_value_for(const T& x) noexcept;

}

#endif // YK_HASH_HASH_VALUE_FOR_FWD_HPP
25 changes: 25 additions & 0 deletions include/yk/hash/range.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#ifndef YK_HASH_RANGE_HPP
#define YK_HASH_RANGE_HPP

#include "yk/hash/hash_value_for/fwd.hpp"

#include <boost/container_hash/hash_fwd.hpp>

#include <ranges>
#include <utility>

#include <cassert>
#include <cstddef>

namespace yk {

template <std::ranges::range R>
[[nodiscard]] constexpr std::size_t hash_range(R&& r) noexcept {
std::size_t seed = 0;
for (auto&& elem : r) boost::hash_combine(seed, ::yk::hash_value_for(elem));
return seed;
}

} // namespace yk

#endif // YK_HASH_RANGE_HPP
24 changes: 0 additions & 24 deletions include/yk/hash/std.hpp

This file was deleted.

13 changes: 10 additions & 3 deletions test/test.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#include "yk/allocator/default_init_allocator.hpp"
#include "yk/bitmask_enum.hpp"
#include "yk/hash.hpp"
#include "yk/hash/adapt.hpp"
#include "yk/hash/boost.hpp"
#include "yk/hash/hash_combine.hpp"
#include "yk/hash/hash_value_for.hpp"
#include "yk/hash/range.hpp"
#include "yk/maybe_mutex.hpp"
#include "yk/par_for_each.hpp"
#include "yk/proxy_hash.hpp"
Expand Down Expand Up @@ -455,7 +455,8 @@ BOOST_AUTO_TEST_CASE(Hash) {

{
hash_test::MultiS s{31415, 9265, 3589};
std::size_t seed = yk::hash_value_for(s.a);
std::size_t seed = 0;
boost::hash_combine(seed, yk::hash_value_for(s.a));
boost::hash_combine(seed, yk::hash_value_for(s.b));
boost::hash_combine(seed, yk::hash_value_for(s.c));
BOOST_TEST(hash_value(s) == seed);
Expand Down Expand Up @@ -489,6 +490,12 @@ BOOST_AUTO_TEST_CASE(StringHash) {
BOOST_TEST(set.contains("foo"sv));
}

BOOST_AUTO_TEST_CASE(RangeHash) {
std::vector vec{3, 1, 4, 1, 5};
BOOST_TEST(yk::hash_range(vec) == yk::hash_combine(3, 1, 4, 1, 5));
BOOST_TEST(yk::hash_combine(33, vec, 4) == yk::hash_combine(33, yk::hash_combine(3, 1, 4, 1, 5), 4));
}

BOOST_AUTO_TEST_CASE(Enum) {
using namespace enum_test;
using namespace yk::bitmask_operators;
Expand Down

0 comments on commit d1d6b59

Please sign in to comment.