Skip to content

Commit b3c7d25

Browse files
[ADT] Use a C++17 fold expression in hash_combine (NFC) (#159901)
combine() combines hash values with recursion on variadic parameters. This patch replaces the recursion with a C++17 fold expression: (combine_data(length, buffer_ptr, buffer_end, get_hashable_data(args)), ...); which expands to: combine_data(length, buffer_ptr, buffer_end, get_hashable_data(a)); combine_data(length, buffer_ptr, buffer_end, get_hashable_data(b)); combine_data(length, buffer_ptr, buffer_end, get_hashable_data(c)); : A key benefit of this change is the unification of the recursive step and the base case. The argument processing and finalization logic now exist as straight-line code within a single function. combine_data now takes buffer_ptr by reference. This is necessary because the previous assignment pattern: buffer_ptr = combine_data(...) is syntactically incompatible with a fold expression. The new pattern: (combine_data(...), ...) discards return values, so combine_data must update buffer_ptr directly. For readability, this patch does the bare minimum to use a fold expression, leaving further cleanups to subsequent patches. For example, buffer_ptr and buffer_end could become member variables, and several comments that mention recursion still need updating.
1 parent 507f394 commit b3c7d25

File tree

1 file changed

+9
-14
lines changed

1 file changed

+9
-14
lines changed

llvm/include/llvm/ADT/Hashing.h

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,8 @@ struct hash_combine_recursive_helper {
503503
/// hash_state, empties it, and then merges the new chunk in. This also
504504
/// handles cases where the data straddles the end of the buffer.
505505
template <typename T>
506-
char *combine_data(size_t &length, char *buffer_ptr, char *buffer_end, T data) {
506+
char *combine_data(size_t &length, char *&buffer_ptr, char *buffer_end,
507+
T data) {
507508
if (!store_and_advance(buffer_ptr, buffer_end, data)) {
508509
// Check for skew which prevents the buffer from being packed, and do
509510
// a partial store into the buffer to fill it. This is only a concern
@@ -541,21 +542,15 @@ struct hash_combine_recursive_helper {
541542
///
542543
/// This function recurses through each argument, combining that argument
543544
/// into a single hash.
544-
template <typename T, typename ...Ts>
545+
template <typename... Ts>
545546
hash_code combine(size_t length, char *buffer_ptr, char *buffer_end,
546-
const T &arg, const Ts &...args) {
547-
buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg));
547+
const Ts &...args) {
548+
((void)combine_data(length, buffer_ptr, buffer_end,
549+
get_hashable_data(args)),
550+
...);
548551

549-
// Recurse to the next argument.
550-
return combine(length, buffer_ptr, buffer_end, args...);
551-
}
552-
553-
/// Base case for recursive, variadic combining.
554-
///
555-
/// The base case when combining arguments recursively is reached when all
556-
/// arguments have been handled. It flushes the remaining buffer and
557-
/// constructs a hash_code.
558-
hash_code combine(size_t length, char *buffer_ptr, char *buffer_end) {
552+
// Finalize the hash by flushing any remaining data in the buffer.
553+
//
559554
// Check whether the entire set of values fit in the buffer. If so, we'll
560555
// use the optimized short hashing routine and skip state entirely.
561556
if (length == 0)

0 commit comments

Comments
 (0)