Skip to content

Commit

Permalink
Factor out hash-combine function
Browse files Browse the repository at this point in the history
Can be improved separately if folks want to submit PRs
  • Loading branch information
hsutter committed Oct 1, 2024
1 parent baa6954 commit c5feb42
Show file tree
Hide file tree
Showing 11 changed files with 65 additions and 57 deletions.
8 changes: 8 additions & 0 deletions include/cpp2util.h
Original file line number Diff line number Diff line change
Expand Up @@ -780,6 +780,14 @@ inline auto pointer_eq(T const* a, T const* b) {
return std::compare_three_way{}(a, b) == std::strong_ordering::equal;
}

// PRs welcome to improve this, for suggestions and background see
// https://www.boost.org/doc/libs/1_86_0/libs/container_hash/doc/html/hash.html#notes_hash_combine
inline auto hash_combine(size_t& seed, size_t v) -> void
{
seed ^= v + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}


//-----------------------------------------------------------------------
//
// A type_find_if for iterating over types in parameter packs
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
6440649391998984779
6443762454025613088
Original file line number Diff line number Diff line change
@@ -1,66 +1,66 @@
In file included from pure2-default-arguments.cpp:7:
../../../include/cpp2util.h:2086:28: error: local variable ‘obj’ may not appear in this context
2086 | template<typename T, std::same_as<std::any> X>
| ^~~
2086 | }
| ^
../../../include/cpp2util.h:2047:34: note: in definition of macro ‘CPP2_UFCS_IDENTITY’
2047 | return false;
2047 | )
| ^
../../../include/cpp2util.h:2086:15: note: in expansion of macro ‘CPP2_FORWARD’
2086 | template<typename T, std::same_as<std::any> X>
| ^~~~~~~~~~~~
2086 | }
| ^
../../../include/cpp2util.h:2107:22: note: in expansion of macro ‘CPP2_UFCS_CONSTRAINT_ARG’
2107 | }
| ^
2107 | if constexpr (valid_predicate<decltype(value), decltype(x)>) {
| ^~~~~~~~~~~~~~~~~~~~~~~~
../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’
2137 | return false;
| ^
2137 | template<typename T, specialization_of_template<std::optional> X>
| ^~~~~~~
pure2-default-arguments.cpp2:6:22: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’
../../../include/cpp2util.h:2086:92: error: local variable ‘params’ may not appear in this context
2086 | template<typename T, std::same_as<std::any> X>
2086 | }
| ^
../../../include/cpp2util.h:2047:34: note: in definition of macro ‘CPP2_UFCS_IDENTITY’
2047 | return false;
2047 | )
| ^
../../../include/cpp2util.h:2086:79: note: in expansion of macro ‘CPP2_FORWARD’
2086 | template<typename T, std::same_as<std::any> X>
2086 | }
| ^
../../../include/cpp2util.h:2107:22: note: in expansion of macro ‘CPP2_UFCS_CONSTRAINT_ARG’
2107 | }
| ^
2107 | if constexpr (valid_predicate<decltype(value), decltype(x)>) {
| ^~~~~~~~~~~~~~~~~~~~~~~~
../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’
2137 | return false;
| ^
2137 | template<typename T, specialization_of_template<std::optional> X>
| ^~~~~~~
pure2-default-arguments.cpp2:6:22: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’
../../../include/cpp2util.h:2087:74: error: local variable ‘obj’ may not appear in this context
2087 | constexpr auto is( X const& x ) -> bool{
2087 |
| ^
../../../include/cpp2util.h:2047:34: note: in definition of macro ‘CPP2_UFCS_IDENTITY’
2047 | return false;
2047 | )
| ^
../../../include/cpp2util.h:2087:61: note: in expansion of macro ‘CPP2_FORWARD’
2087 | constexpr auto is( X const& x ) -> bool{
2087 |
| ^
../../../include/cpp2util.h:2107:22: note: in expansion of macro ‘CPP2_UFCS_CONSTRAINT_ARG’
2107 | }
| ^
2107 | if constexpr (valid_predicate<decltype(value), decltype(x)>) {
| ^~~~~~~~~~~~~~~~~~~~~~~~
../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’
2137 | return false;
| ^
2137 | template<typename T, specialization_of_template<std::optional> X>
| ^~~~~~~
pure2-default-arguments.cpp2:6:22: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’
../../../include/cpp2util.h:2087:93: error: local variable ‘params’ may not appear in this context
2087 | constexpr auto is( X const& x ) -> bool{
2087 |
| ^
../../../include/cpp2util.h:2047:34: note: in definition of macro ‘CPP2_UFCS_IDENTITY’
2047 | return false;
2047 | )
| ^
../../../include/cpp2util.h:2087:80: note: in expansion of macro ‘CPP2_FORWARD’
2087 | constexpr auto is( X const& x ) -> bool{
2087 |
| ^
../../../include/cpp2util.h:2107:22: note: in expansion of macro ‘CPP2_UFCS_CONSTRAINT_ARG’
2107 | }
| ^
2107 | if constexpr (valid_predicate<decltype(value), decltype(x)>) {
| ^~~~~~~~~~~~~~~~~~~~~~~~
../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’
2137 | return false;
| ^
2137 | template<typename T, specialization_of_template<std::optional> X>
| ^~~~~~~
pure2-default-arguments.cpp2:6:22: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’
pure2-default-arguments.cpp2:6:61: error: ‘std::source_location’ has not been declared
Original file line number Diff line number Diff line change
@@ -1,41 +1,41 @@
In file included from mixed-bugfix-for-ufcs-non-local.cpp:6:
../../../include/cpp2util.h:2100:1: error: lambda-expression in template parameter type
2100 | return value(x);
2100 | }
| ^
../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’
2137 | return false;
| ^
2137 | template<typename T, specialization_of_template<std::optional> X>
| ^~~~~~~
mixed-bugfix-for-ufcs-non-local.cpp2:13:12: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’
mixed-bugfix-for-ufcs-non-local.cpp2:13:36: error: template argument 1 is invalid
../../../include/cpp2util.h:2100:1: error: lambda-expression in template parameter type
2100 | return value(x);
2100 | }
| ^
../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’
2137 | return false;
| ^
2137 | template<typename T, specialization_of_template<std::optional> X>
| ^~~~~~~
mixed-bugfix-for-ufcs-non-local.cpp2:21:12: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’
mixed-bugfix-for-ufcs-non-local.cpp2:21:36: error: template argument 1 is invalid
../../../include/cpp2util.h:2100:1: error: lambda-expression in template parameter type
2100 | return value(x);
2100 | }
| ^
../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’
2137 | return false;
| ^
2137 | template<typename T, specialization_of_template<std::optional> X>
| ^~~~~~~
mixed-bugfix-for-ufcs-non-local.cpp2:31:12: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’
mixed-bugfix-for-ufcs-non-local.cpp2:31:36: error: template argument 1 is invalid
../../../include/cpp2util.h:2100:1: error: lambda-expression in template parameter type
2100 | return value(x);
2100 | }
| ^
../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’
2137 | return false;
| ^
2137 | template<typename T, specialization_of_template<std::optional> X>
| ^~~~~~~
mixed-bugfix-for-ufcs-non-local.cpp2:33:12: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’
mixed-bugfix-for-ufcs-non-local.cpp2:33:36: error: template argument 1 is invalid
../../../include/cpp2util.h:2100:1: error: lambda-expression in template parameter type
2100 | return value(x);
2100 | }
| ^
../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’
2137 | return false;
| ^
2137 | template<typename T, specialization_of_template<std::optional> X>
| ^~~~~~~
mixed-bugfix-for-ufcs-non-local.cpp2:21:12: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’
mixed-bugfix-for-ufcs-non-local.cpp2:21:36: error: template argument 1 is invalid
Original file line number Diff line number Diff line change
@@ -1 +1 @@
6440649391998984779
6443762454025613088
Original file line number Diff line number Diff line change
@@ -1 +1 @@
13958440649017415620
13929407477532509065
10 changes: 5 additions & 5 deletions regression-tests/test-results/pure2-hashable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ requires (std::is_convertible_v<CPP2_TYPEOF(h_), std::add_const_t<cpp2::i32>&>)
[[nodiscard]] auto base::hash() const& -> size_t{

size_t ret {0};
ret ^= std::hash<cpp2::i32>()(h) + (ret << 6) + (ret >> 2);
cpp2::hash_combine(ret, std::hash<cpp2::i32>()(h));
return ret;
}

Expand All @@ -73,10 +73,10 @@ requires (std::is_convertible_v<CPP2_TYPEOF(i_), std::add_const_t<cpp2::i32>&> &
[[nodiscard]] auto mystruct::hash() const& -> size_t{

size_t ret {0};
ret ^= base::hash() + (ret << 6) + (ret >> 2);
ret ^= std::hash<cpp2::i32>()(i) + (ret << 6) + (ret >> 2);
ret ^= std::hash<std::string>()(j) + (ret << 6) + (ret >> 2);
ret ^= std::hash<cpp2::u64>()(k) + (ret << 6) + (ret >> 2);
cpp2::hash_combine(ret, base::hash());
cpp2::hash_combine(ret, std::hash<cpp2::i32>()(i));
cpp2::hash_combine(ret, std::hash<std::string>()(j));
cpp2::hash_combine(ret, std::hash<cpp2::u64>()(k));
return ret;
}
#line 12 "pure2-hashable.cpp2"
Expand Down
2 changes: 1 addition & 1 deletion regression-tests/test-results/version
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

cppfront compiler v0.7.4 Build 9930:1349
cppfront compiler v0.7.4 Build 9930:1408
Copyright(c) Herb Sutter All rights reserved

SPDX-License-Identifier: CC-BY-NC-ND-4.0
Expand Down
2 changes: 1 addition & 1 deletion source/build.info
Original file line number Diff line number Diff line change
@@ -1 +1 @@
"9930:1349"
"9930:1408"
2 changes: 1 addition & 1 deletion source/reflect.h
Original file line number Diff line number Diff line change
Expand Up @@ -2419,7 +2419,7 @@ auto hashable(meta::type_declaration& t) -> void
o_hash.construct("std::hash<" + cpp2::to_string(CPP2_UFCS(type)(o)) + ">()(" + cpp2::to_string(CPP2_UFCS(name)(o)) + ")");
}

hash += "\n ret ^= " + cpp2::to_string(cpp2::move(o_hash.value())) + " + (ret << 6) + (ret >> 2);";
hash += "\n cpp2::hash_combine( ret, " + cpp2::to_string(cpp2::move(o_hash.value())) + " );";
}

CPP2_UFCS(add_member)(t, cpp2::move(hash) + "\n return ret;\n }");
Expand Down
2 changes: 1 addition & 1 deletion source/reflect.h2
Original file line number Diff line number Diff line change
Expand Up @@ -858,7 +858,7 @@ hashable: (inout t: meta::type_declaration) =
o_hash = "std::hash<(o.type())$>()((o.name())$)";
}

hash += "\n ret ^= (o_hash)$ + (ret << 6) + (ret >> 2);";
hash += "\n cpp2::hash_combine( ret, (o_hash)$ );";
}

t.add_member(hash + "\n return ret;\n }");
Expand Down

0 comments on commit c5feb42

Please sign in to comment.