Skip to content

Commit c5feb42

Browse files
committed
Factor out hash-combine function
Can be improved separately if folks want to submit PRs
1 parent baa6954 commit c5feb42

File tree

11 files changed

+65
-57
lines changed

11 files changed

+65
-57
lines changed

include/cpp2util.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -780,6 +780,14 @@ inline auto pointer_eq(T const* a, T const* b) {
780780
return std::compare_three_way{}(a, b) == std::strong_ordering::equal;
781781
}
782782

783+
// PRs welcome to improve this, for suggestions and background see
784+
// https://www.boost.org/doc/libs/1_86_0/libs/container_hash/doc/html/hash.html#notes_hash_combine
785+
inline auto hash_combine(size_t& seed, size_t v) -> void
786+
{
787+
seed ^= v + 0x9e3779b9 + (seed << 6) + (seed >> 2);
788+
}
789+
790+
783791
//-----------------------------------------------------------------------
784792
//
785793
// A type_find_if for iterating over types in parameter packs
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
6440649391998984779
1+
6443762454025613088
Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,66 @@
11
In file included from pure2-default-arguments.cpp:7:
22
../../../include/cpp2util.h:2086:28: error: local variable ‘obj’ may not appear in this context
3-
2086 | template<typename T, std::same_as<std::any> X>
4-
| ^~~
3+
2086 | }
4+
| ^
55
../../../include/cpp2util.h:2047:34: note: in definition of macro ‘CPP2_UFCS_IDENTITY’
6-
2047 | return false;
6+
2047 | )
77
| ^
88
../../../include/cpp2util.h:2086:15: note: in expansion of macro ‘CPP2_FORWARD’
9-
2086 | template<typename T, std::same_as<std::any> X>
10-
| ^~~~~~~~~~~~
9+
2086 | }
10+
| ^
1111
../../../include/cpp2util.h:2107:22: note: in expansion of macro ‘CPP2_UFCS_CONSTRAINT_ARG’
12-
2107 | }
13-
| ^
12+
2107 | if constexpr (valid_predicate<decltype(value), decltype(x)>) {
13+
| ^~~~~~~~~~~~~~~~~~~~~~~~
1414
../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’
15-
2137 | return false;
16-
| ^
15+
2137 | template<typename T, specialization_of_template<std::optional> X>
16+
| ^~~~~~~
1717
pure2-default-arguments.cpp2:6:22: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’
1818
../../../include/cpp2util.h:2086:92: error: local variable ‘params’ may not appear in this context
19-
2086 | template<typename T, std::same_as<std::any> X>
19+
2086 | }
2020
| ^
2121
../../../include/cpp2util.h:2047:34: note: in definition of macro ‘CPP2_UFCS_IDENTITY’
22-
2047 | return false;
22+
2047 | )
2323
| ^
2424
../../../include/cpp2util.h:2086:79: note: in expansion of macro ‘CPP2_FORWARD’
25-
2086 | template<typename T, std::same_as<std::any> X>
25+
2086 | }
2626
| ^
2727
../../../include/cpp2util.h:2107:22: note: in expansion of macro ‘CPP2_UFCS_CONSTRAINT_ARG’
28-
2107 | }
29-
| ^
28+
2107 | if constexpr (valid_predicate<decltype(value), decltype(x)>) {
29+
| ^~~~~~~~~~~~~~~~~~~~~~~~
3030
../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’
31-
2137 | return false;
32-
| ^
31+
2137 | template<typename T, specialization_of_template<std::optional> X>
32+
| ^~~~~~~
3333
pure2-default-arguments.cpp2:6:22: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’
3434
../../../include/cpp2util.h:2087:74: error: local variable ‘obj’ may not appear in this context
35-
2087 | constexpr auto is( X const& x ) -> bool{
35+
2087 |
3636
| ^
3737
../../../include/cpp2util.h:2047:34: note: in definition of macro ‘CPP2_UFCS_IDENTITY’
38-
2047 | return false;
38+
2047 | )
3939
| ^
4040
../../../include/cpp2util.h:2087:61: note: in expansion of macro ‘CPP2_FORWARD’
41-
2087 | constexpr auto is( X const& x ) -> bool{
41+
2087 |
4242
| ^
4343
../../../include/cpp2util.h:2107:22: note: in expansion of macro ‘CPP2_UFCS_CONSTRAINT_ARG’
44-
2107 | }
45-
| ^
44+
2107 | if constexpr (valid_predicate<decltype(value), decltype(x)>) {
45+
| ^~~~~~~~~~~~~~~~~~~~~~~~
4646
../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’
47-
2137 | return false;
48-
| ^
47+
2137 | template<typename T, specialization_of_template<std::optional> X>
48+
| ^~~~~~~
4949
pure2-default-arguments.cpp2:6:22: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’
5050
../../../include/cpp2util.h:2087:93: error: local variable ‘params’ may not appear in this context
51-
2087 | constexpr auto is( X const& x ) -> bool{
51+
2087 |
5252
| ^
5353
../../../include/cpp2util.h:2047:34: note: in definition of macro ‘CPP2_UFCS_IDENTITY’
54-
2047 | return false;
54+
2047 | )
5555
| ^
5656
../../../include/cpp2util.h:2087:80: note: in expansion of macro ‘CPP2_FORWARD’
57-
2087 | constexpr auto is( X const& x ) -> bool{
57+
2087 |
5858
| ^
5959
../../../include/cpp2util.h:2107:22: note: in expansion of macro ‘CPP2_UFCS_CONSTRAINT_ARG’
60-
2107 | }
61-
| ^
60+
2107 | if constexpr (valid_predicate<decltype(value), decltype(x)>) {
61+
| ^~~~~~~~~~~~~~~~~~~~~~~~
6262
../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’
63-
2137 | return false;
64-
| ^
63+
2137 | template<typename T, specialization_of_template<std::optional> X>
64+
| ^~~~~~~
6565
pure2-default-arguments.cpp2:6:22: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’
6666
pure2-default-arguments.cpp2:6:61: error: ‘std::source_location’ has not been declared
Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,41 @@
11
In file included from mixed-bugfix-for-ufcs-non-local.cpp:6:
22
../../../include/cpp2util.h:2100:1: error: lambda-expression in template parameter type
3-
2100 | return value(x);
3+
2100 | }
44
| ^
55
../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’
6-
2137 | return false;
7-
| ^
6+
2137 | template<typename T, specialization_of_template<std::optional> X>
7+
| ^~~~~~~
88
mixed-bugfix-for-ufcs-non-local.cpp2:13:12: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’
99
mixed-bugfix-for-ufcs-non-local.cpp2:13:36: error: template argument 1 is invalid
1010
../../../include/cpp2util.h:2100:1: error: lambda-expression in template parameter type
11-
2100 | return value(x);
11+
2100 | }
1212
| ^
1313
../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’
14-
2137 | return false;
15-
| ^
14+
2137 | template<typename T, specialization_of_template<std::optional> X>
15+
| ^~~~~~~
1616
mixed-bugfix-for-ufcs-non-local.cpp2:21:12: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’
1717
mixed-bugfix-for-ufcs-non-local.cpp2:21:36: error: template argument 1 is invalid
1818
../../../include/cpp2util.h:2100:1: error: lambda-expression in template parameter type
19-
2100 | return value(x);
19+
2100 | }
2020
| ^
2121
../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’
22-
2137 | return false;
23-
| ^
22+
2137 | template<typename T, specialization_of_template<std::optional> X>
23+
| ^~~~~~~
2424
mixed-bugfix-for-ufcs-non-local.cpp2:31:12: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’
2525
mixed-bugfix-for-ufcs-non-local.cpp2:31:36: error: template argument 1 is invalid
2626
../../../include/cpp2util.h:2100:1: error: lambda-expression in template parameter type
27-
2100 | return value(x);
27+
2100 | }
2828
| ^
2929
../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’
30-
2137 | return false;
31-
| ^
30+
2137 | template<typename T, specialization_of_template<std::optional> X>
31+
| ^~~~~~~
3232
mixed-bugfix-for-ufcs-non-local.cpp2:33:12: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’
3333
mixed-bugfix-for-ufcs-non-local.cpp2:33:36: error: template argument 1 is invalid
3434
../../../include/cpp2util.h:2100:1: error: lambda-expression in template parameter type
35-
2100 | return value(x);
35+
2100 | }
3636
| ^
3737
../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’
38-
2137 | return false;
39-
| ^
38+
2137 | template<typename T, specialization_of_template<std::optional> X>
39+
| ^~~~~~~
4040
mixed-bugfix-for-ufcs-non-local.cpp2:21:12: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’
4141
mixed-bugfix-for-ufcs-non-local.cpp2:21:36: error: template argument 1 is invalid
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
6440649391998984779
1+
6443762454025613088
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
13958440649017415620
1+
13929407477532509065

regression-tests/test-results/pure2-hashable.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ requires (std::is_convertible_v<CPP2_TYPEOF(h_), std::add_const_t<cpp2::i32>&>)
6060
[[nodiscard]] auto base::hash() const& -> size_t{
6161

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

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

7575
size_t ret {0};
76-
ret ^= base::hash() + (ret << 6) + (ret >> 2);
77-
ret ^= std::hash<cpp2::i32>()(i) + (ret << 6) + (ret >> 2);
78-
ret ^= std::hash<std::string>()(j) + (ret << 6) + (ret >> 2);
79-
ret ^= std::hash<cpp2::u64>()(k) + (ret << 6) + (ret >> 2);
76+
cpp2::hash_combine(ret, base::hash());
77+
cpp2::hash_combine(ret, std::hash<cpp2::i32>()(i));
78+
cpp2::hash_combine(ret, std::hash<std::string>()(j));
79+
cpp2::hash_combine(ret, std::hash<cpp2::u64>()(k));
8080
return ret;
8181
}
8282
#line 12 "pure2-hashable.cpp2"

regression-tests/test-results/version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
cppfront compiler v0.7.4 Build 9930:1349
2+
cppfront compiler v0.7.4 Build 9930:1408
33
Copyright(c) Herb Sutter All rights reserved
44

55
SPDX-License-Identifier: CC-BY-NC-ND-4.0

source/build.info

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
"9930:1349"
1+
"9930:1408"

source/reflect.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2419,7 +2419,7 @@ auto hashable(meta::type_declaration& t) -> void
24192419
o_hash.construct("std::hash<" + cpp2::to_string(CPP2_UFCS(type)(o)) + ">()(" + cpp2::to_string(CPP2_UFCS(name)(o)) + ")");
24202420
}
24212421

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

24252425
CPP2_UFCS(add_member)(t, cpp2::move(hash) + "\n return ret;\n }");

source/reflect.h2

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -858,7 +858,7 @@ hashable: (inout t: meta::type_declaration) =
858858
o_hash = "std::hash<(o.type())$>()((o.name())$)";
859859
}
860860

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

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

0 commit comments

Comments
 (0)