kblib 0.2.3
General utilities library for modern C++
hash.h
Go to the documentation of this file.
1/* *****************************************************************************
2 * kblib is a general utility library for C++14 and C++17, intended to provide
3 * performant high-level abstractions and more expressive ways to do simple
4 * things.
5 *
6 * Copyright (c) 2021 killerbee
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 * ****************************************************************************/
21
32#ifndef HASH_H
33#define HASH_H
34
35#include "iterators.h"
36#include "tdecl.h"
37#include "traits.h"
38#include "variant.h"
39
40#include <climits>
41#include <cstdint>
42#include <numeric>
43#include <string>
44#include <unordered_map>
45#include <unordered_set>
46
47#if KBLIB_USE_CXX17
48# include <optional>
49# include <string_view>
50# include <variant>
51#endif
52
53namespace kblib {
54
55template <typename Integral, typename CharT>
56constexpr auto to_bytes_le(Integral ival,
57 CharT (&dest)[sizeof(Integral)]) noexcept -> void {
58 static_assert(std::is_integral<CharT>::value and sizeof(CharT) == 1
59 and not std::is_same<CharT, bool>::value,
60 "CharT must be a char-like type.");
61 for (int byte = 0; byte != sizeof(Integral); ++byte) {
62 dest[byte] = static_cast<CharT>(to_unsigned(ival)
63 >> to_unsigned(CHAR_BIT * byte));
64 }
65}
66
67template <typename Integral, typename CharT>
68constexpr auto to_bytes_be(Integral ival,
69 CharT (&dest)[sizeof(Integral)]) noexcept -> void {
70 static_assert(std::is_integral<CharT>::value and sizeof(CharT) == 1
71 and not std::is_same<CharT, bool>::value,
72 "CharT must be a char-like type.");
73 for (auto byte : range(sizeof(Integral))) {
74 dest[(sizeof(Integral) - 1) - byte]
75 = static_cast<CharT>(ival >> (CHAR_BIT * byte));
76 }
77}
78
79template <typename Integral, typename CharT>
80constexpr auto to_bytes(Integral val, CharT (&dest)[sizeof(Integral)]) noexcept
81 -> void {
82 static_assert(std::is_integral<CharT>::value and sizeof(CharT) == 1
83 and not std::is_same<CharT, bool>::value,
84 "CharT must be a char-like type.");
86 to_bytes_le(val, dest);
87 } else {
88 to_bytes_be(val, dest);
89 }
90}
91
92namespace fnv {
93
97 template <typename UInt>
98 struct fnv_prime;
99
100 template <>
101 struct fnv_prime<std::uint32_t>
102 : std::integral_constant<std::uint32_t, 16777619ul> {};
103 template <>
104 struct fnv_prime<std::uint64_t>
105 : std::integral_constant<std::uint64_t, 1099511628211ull> {};
106
107 template <typename UInt>
108 struct fnv_prime {
109 KBLIB_CONSTANT_M UInt value = (sizeof(UInt) == sizeof(std::uint64_t)
112 };
113
117 template <typename UInt>
118 struct fnv_offset;
119
120 template <>
121 struct fnv_offset<std::uint32_t>
122 : std::integral_constant<std::uint32_t, 2166136261ul> {};
123 template <>
124 struct fnv_offset<std::uint64_t>
125 : std::integral_constant<std::uint64_t, 14695981039346656037ull> {};
126
127 template <typename UInt>
128 struct fnv_offset {
129 KBLIB_CONSTANT_M UInt value = (sizeof(UInt) == sizeof(std::uint64_t)
132 };
133
134} // namespace fnv
135
146template <typename HashInt, typename Span>
147KBLIB_NODISCARD constexpr auto FNVa(Span&& s,
148 HashInt hval
150 -> HashInt {
151 static_assert(sizeof(*std::begin(s)) == 1,
152 "Can only hash char-like objects.");
153 const HashInt prime = fnv::fnv_prime<HashInt>::value;
154 for (auto&& c : s) {
155 hval ^= static_cast<HashInt>(static_cast<unsigned char>(c));
156 hval *= prime;
157 }
158 return hval;
159}
160
172template <typename HashInt, typename CharT, std::size_t N>
173KBLIB_NODISCARD constexpr auto FNVa_a(
174 const CharT (&s)[N],
175 HashInt hval = fnv::fnv_offset<HashInt>::value) noexcept -> HashInt {
176 static_assert(sizeof(s[0]) == 1, "Can only hash char-like objects.");
177 const HashInt prime = fnv::fnv_prime<HashInt>::value;
178 for (auto&& c : s) {
179 hval ^= static_cast<HashInt>(static_cast<unsigned char>(c));
180 hval *= prime;
181 }
182 return hval;
183}
184
185#if KBLIB_USE_CXX17
194KBLIB_NODISCARD constexpr auto FNV32a(
195 std::string_view s,
196 std::uint32_t hval = fnv::fnv_offset<std::uint32_t>::value) noexcept
197 -> std::uint32_t {
198 const std::uint32_t prime = fnv::fnv_prime<std::uint32_t>::value;
199 for (auto&& c : s) {
200 hval ^= static_cast<std::uint32_t>(static_cast<unsigned char>(c));
201 hval *= prime;
202 }
203 return hval;
204}
205#endif
206
207template <typename HashInt>
208KBLIB_NODISCARD constexpr auto FNVa_s(
209 const char* begin, std::size_t length,
210 HashInt hval = fnv::fnv_offset<HashInt>::value) noexcept -> HashInt {
211 const HashInt prime = fnv::fnv_prime<HashInt>::value;
212 // for (const char* pos = begin; pos != begin + length; ++pos) {
213 // hval ^= static_cast<HashInt>(static_cast<unsigned char>(*pos));
214 // hval *= prime;
215 // }
216 for (const char* pos : range(begin, begin + length)) {
217 hval ^= static_cast<HashInt>(static_cast<unsigned char>(*pos));
218 hval *= prime;
219 }
220 return hval;
221}
222
232template <std::size_t N>
234 const char (&s)[N],
235 std::uint32_t hval = fnv::fnv_offset<std::uint32_t>::value) noexcept
236 -> std::uint32_t {
237 const std::uint32_t prime = fnv::fnv_prime<std::uint32_t>::value;
238 for (auto&& c : s) {
239 hval ^= static_cast<std::uint32_t>(static_cast<unsigned char>(c));
240 hval *= prime;
241 }
242 return hval;
243}
244
246 const char* begin, std::size_t length,
247 uint32_t hval = fnv::fnv_offset<std::uint32_t>::value) noexcept
248 -> std::uint32_t {
249 const std::uint32_t prime = fnv::fnv_prime<std::uint32_t>::value;
250 for (const char* pos = begin; pos != begin + length; ++pos) {
251 hval ^= static_cast<std::uint32_t>(static_cast<unsigned char>(*pos));
252 hval *= prime;
253 }
254 return hval;
255}
256
257inline namespace literals {
261 KBLIB_NODISCARD constexpr auto operator""_fnv32(const char* str,
262 std::size_t length) noexcept
263 -> std::uint32_t {
264 return FNVa_s<std::uint32_t>(str, length);
265 }
266
270 KBLIB_NODISCARD constexpr auto operator""_fnv64(const char* str,
271 std::size_t length) noexcept
272 -> std::uint64_t {
273 return FNVa_s<std::uint64_t>(str, length);
274 }
275
276 // google-runtime-int not relevant here due to standard requirements
277 KBLIB_NODISCARD constexpr auto operator""_fnv32(unsigned long long val)
278 -> std::uint32_t {
279 unsigned char bytes[sizeof(unsigned long long)]{};
280 to_bytes(val, bytes);
281 return FNVa_a<std::uint32_t>(bytes);
282 }
283
284 KBLIB_NODISCARD constexpr auto operator""_fnv64(unsigned long long val)
285 -> std::uint64_t {
286 unsigned char bytes[sizeof(unsigned long long)]{};
287 to_bytes(val, bytes);
288 return FNVa_a<std::uint64_t>(bytes);
289 }
290
291} // namespace literals
292
293#if KBLIB_USE_CXX17
299template <typename T>
300constexpr int padding_bits_v
301 = CHAR_BIT * sizeof(T) - std::numeric_limits<T>::digits
302 - std::numeric_limits<T>::is_signed;
303
304template <>
305inline constexpr int padding_bits_v<void> = 0;
306
307template <typename T>
308struct padding_bits : std::integral_constant<int, padding_bits_v<T>> {};
309#else
310
315template <typename T>
316struct padding_bits
317 : std::integral_constant<int, CHAR_BIT * sizeof(T)
318 - std::numeric_limits<T>::digits
319 - std::numeric_limits<T>::is_signed> {};
320template <>
321struct padding_bits<void> : std::integral_constant<int, 0> {};
322
323template <typename T>
324constexpr int padding_bits_v = padding_bits<T>::value;
325
326#endif
327
333template <typename Key = void, typename HashInt = std::size_t, typename = void>
334struct FNV_hash {
335 FNV_hash() = delete;
336 FNV_hash(const FNV_hash&) = delete;
337 FNV_hash(FNV_hash&&) = delete;
338 FNV_hash& operator=(const FNV_hash&) = delete;
340};
341
342template <typename Key, typename = void>
343struct is_hashable : std::false_type {};
344
345template <typename Key>
346struct is_hashable<Key, void_if_t<std::is_constructible<FNV_hash<Key>>::value>>
347 : std::true_type {};
348
349template <typename Key>
351
352template <typename Key>
354
359template <typename HashInt>
360struct FNV_hash<bool, HashInt, void> {
362 bool key, HashInt offset
363 = fnv::fnv_offset<HashInt>::value) const noexcept -> HashInt {
364 char tmp[1] = {key};
365 return FNVa_a(tmp, offset);
366 }
367};
368
373template <typename HashInt>
374struct FNV_hash<char, HashInt, void> {
376 char key, HashInt offset
377 = fnv::fnv_offset<HashInt>::value) const noexcept -> HashInt {
378 char tmp[1] = {key};
379 return FNVa_a(tmp, offset);
380 }
381};
382
387template <typename HashInt>
388struct FNV_hash<signed char, HashInt, void> {
390 signed char key,
391 HashInt offset = fnv::fnv_offset<HashInt>::value) const noexcept
392 -> HashInt {
393 signed char tmp[1] = {key};
394 return FNVa_a(tmp, offset);
395 }
396};
397
402template <typename HashInt>
403struct FNV_hash<unsigned char, HashInt, void> {
405 unsigned char key,
406 HashInt offset = fnv::fnv_offset<HashInt>::value) const noexcept
407 -> HashInt {
408 unsigned char tmp[1] = {key};
409 return FNVa_a(tmp, offset);
410 }
411};
412
416template <typename T, typename HashInt>
417struct FNV_hash<T, HashInt, void_if_t<std::is_empty<T>::value>> {
419 const T&, HashInt offset
420 = fnv::fnv_offset<HashInt>::value) const noexcept -> HashInt {
421 return FNVa_a("", offset); // hashes the null terminator
422 }
423};
424
425#if __cpp_lib_has_unique_object_representations
426template <typename T>
428 = (std::is_trivially_copyable_v<
429 T> and std::has_unique_object_representations_v<T> and not std::is_empty<T>::value);
430#else
431template <typename T>
433 = (std::is_integral<T>::value and padding_bits<T>::value == 0)
434 or std::is_pointer<T>::value or std::is_member_object_pointer<T>::value
435 or std::is_member_function_pointer<T>::value;
436#endif
437template <typename T>
438struct is_trivially_hashable : bool_constant<is_trivially_hashable_v<T>> {};
439
444template <typename T, typename HashInt>
445struct FNV_hash<
446 T, HashInt,
447 void_if_t<std::is_integral<T>::value and is_trivially_hashable_v<T>>> {
449 T key, HashInt offset = fnv::fnv_offset<HashInt>::value) const noexcept
450 -> HashInt {
451 unsigned char tmp[sizeof(T)]{};
452 to_bytes(key, tmp);
453 return FNVa_a(tmp, offset);
454 }
455};
456
463// uses std::is_pointer instead of just specializing on T* for cv pointers
464template <typename T, typename HashInt>
465struct FNV_hash<T, HashInt, void_if_t<std::is_pointer<T>::value>> {
467 T key_in, HashInt offset
468 = fnv::fnv_offset<HashInt>::value) const noexcept -> HashInt {
470 reinterpret_cast<std::uintptr_t>(key_in), offset);
471 }
472};
473
480template <typename T, typename HashInt>
481struct FNV_hash<T, HashInt,
482 void_if_t<(std::is_base_of<std::forward_iterator_tag,
483 typename std::iterator_traits<
484 T>::iterator_category>::value and
485 not std::is_pointer<T>::value and
486 not is_trivially_hashable_v<T> and
487 std::is_pointer<typename fakestd::invoke_result<
488 decltype(&T::operator->), T>::type>::value)>> {
490 T key_in, HashInt offset
491 = fnv::fnv_offset<HashInt>::value) const noexcept -> HashInt {
492 if (key_in
493 == T{}) { // avoid calling to_pointer on a value-initialized iterator
494 return FNV_hash<std::uintptr_t, HashInt>{}(0, offset);
495 } else {
497 reinterpret_cast<std::uintptr_t>(to_pointer(key_in)), offset);
498 }
499 }
500};
501
505namespace asserts {
506
507 template <typename Container>
510 and is_trivially_hashable_v<typename Container::value_type>);
511 static_assert(is_trivial_container<std::string>,
512 "kblib bug: std::string should be trivially hashable");
513
514} // namespace asserts
515
520template <typename Container, typename HashInt>
521struct FNV_hash<
522 Container, HashInt,
523 void_if_t<(
525 Container> and is_trivially_hashable_v<typename Container::value_type>)>> {
526
527 KBLIB_NODISCARD auto hash_fast(const Container& key,
528 HashInt offset) const noexcept -> HashInt {
529 return FNVa_s<HashInt>(reinterpret_cast<const char*>(key.data()),
530 key.size() * sizeof(*key.begin()), offset);
531 }
532
534 const Container& key,
535 HashInt offset = fnv::fnv_offset<HashInt>::value) const noexcept
536 -> HashInt {
537#if KBLIB_USE_CXX20
538 if (std::is_constant_evaluated()) {
539 using T = typename Container::value_type;
540 for (const auto& e : key) {
541 offset = FNV_hash<T>{}(e, offset);
542 }
543 } else {
544 return hash_fast(key, offset);
545 }
546#else
547 return hash_fast(key, offset);
548#endif
549 }
550};
551
560template <typename T, typename HashInt>
561struct FNV_hash<
562 T, HashInt,
563 void_if_t<not is_contiguous<T>::value and not std::is_integral<T>::value
564 and not std::is_pointer<T>::value
565 and is_trivially_hashable_v<T>>> {
566 KBLIB_NODISCARD KBLIB_CXX20(constexpr) auto operator()(
567 T key, HashInt offset = fnv::fnv_offset<HashInt>::value) const noexcept
568 -> HashInt {
569 char tmp[sizeof(T)];
570 std::memcpy(tmp, &key, sizeof(T));
571 return FNVa_a(tmp, offset);
572 }
573};
574
579template <typename Container, typename HashInt>
580struct FNV_hash<
581 Container, HashInt,
582 void_if_t<
583 value_detected<Container>::value
584 and is_hashable_v<
585 value_detected_t<Container>> and not hash_detected<Container>::value
586 and is_iterable<Container>::value
587 and not (is_contiguous<Container>::value
588 and is_trivially_hashable_v<typename Container::value_type>)
589 and not is_iterator_v<Container>>> {
591 const Container& key,
592 HashInt offset = fnv::fnv_offset<HashInt>::value) const noexcept
593 -> HashInt {
594 using Elem = typename Container::value_type;
595 return std::accumulate(cbegin(key), cend(key), offset,
596 [](HashInt offset_, const Elem& elem) {
597 return FNV_hash<Elem, HashInt>{}(elem, offset_);
598 });
599 }
600};
601
606namespace detail_hash {
607
616 template <typename Tuple, typename HashInt, std::size_t I>
617 constexpr auto hash_tuple_impl(const Tuple& tuple, HashInt offset,
618 std::index_sequence<I>) noexcept -> HashInt {
620 std::get<I>(tuple), offset);
621 }
622
631 template <typename Tuple, typename HashInt, std::size_t I, std::size_t I2,
632 std::size_t... Is>
633 constexpr auto hash_tuple_impl(const Tuple& tuple, HashInt offset,
634 std::index_sequence<I, I2, Is...>) noexcept
635 -> HashInt {
636 HashInt first_hash
638 std::get<I>(tuple), offset);
639 return hash_tuple_impl(tuple, first_hash,
640 std::index_sequence<I2, Is...>{});
641 }
642
643#if KBLIB_USE_CXX17
644 template <typename Tuple, std::size_t... Is>
645 constexpr auto all_hashable_impl(std::index_sequence<Is...>) -> bool {
646 return (...
647 and is_hashable_v<typename std::tuple_element<Is, Tuple>::type>);
648 }
649#else
650
651 template <typename Tuple, typename IS>
652 struct all_hashable_impl_t;
653
654 template <typename Tuple, std::size_t I, std::size_t... Is>
655 struct all_hashable_impl_t<Tuple, std::index_sequence<I, Is...>>
656 : bool_constant<(
657 is_hashable_v<
658 typename std::tuple_element<I, Tuple>::
659 type> and all_hashable_impl_t<Tuple, std::index_sequence<Is...>>::value)> {
660 };
661
662 template <typename Tuple, std::size_t I>
663 struct all_hashable_impl_t<Tuple, std::index_sequence<I>>
665 is_hashable_v<typename std::tuple_element<I, Tuple>::type>> {};
666
667 template <typename Tuple, std::size_t... Is>
668 constexpr auto all_hashable_impl(std::index_sequence<Is...>) -> bool {
669 return all_hashable_impl_t<Tuple, std::index_sequence<Is...>>::value;
670 }
671#endif
672
673 template <
674 typename Tuple,
675 typename std::enable_if<(std::tuple_size<Tuple>::value > 0u), int>::type
676 = 0>
677 constexpr auto all_hashable() -> bool {
678 return all_hashable_impl<Tuple>(
679 std::make_index_sequence<std::tuple_size<Tuple>::value>{});
680 }
681
682} // namespace detail_hash
683
688template <typename Tuple, typename HashInt>
689struct FNV_hash<Tuple, HashInt,
692 Tuple> and (std::tuple_size<Tuple>::value > 0u)
693 and not is_linear_container_v<Tuple>>> {
695 const Tuple& key,
696 HashInt offset = fnv::fnv_offset<HashInt>::value) const noexcept
697 -> HashInt {
699 key, offset,
700 std::make_index_sequence<std::tuple_size<Tuple>::value>{});
701 }
702};
703
704#if KBLIB_USE_CXX17
705
706template <typename T, typename HashInt>
707struct FNV_hash<std::optional<T>, HashInt, void> {
709 const std::optional<T>& key,
710 HashInt offset = fnv::fnv_offset<HashInt>::value) const noexcept
711 -> HashInt {
712 if (key) {
713 return FNV_hash<T, HashInt>{}(key.value(), offset);
714 } else {
715 return FNV_hash<std::nullopt_t, HashInt>{}(std::nullopt, offset);
716 }
717 }
718};
719
720template <typename... Ts, typename HashInt>
721struct FNV_hash<std::variant<Ts...>, HashInt,
722 void_if_t<detail_hash::all_hashable<std::tuple<Ts...>>()>> {
724 const std::variant<Ts...>& key,
725 HashInt offset = fnv::fnv_offset<HashInt>::value) const noexcept
726 -> HashInt {
727 // Variant index is hashed alongside the value
728 offset = FNV_hash<HashInt>{}(key.index(), offset);
729 // visit2_nop does nothing when the variant is valueless_by_exception
730 kblib::visit2_nop(key, [&](auto& V) {
731 offset = FNV_hash<typename std::remove_reference<decltype(V)>::type,
732 HashInt>{}(V, offset);
733 });
734 return offset;
735 }
736};
737
738#endif
739
744template <typename HashInt>
745struct FNV_hash<void, HashInt, void> {
746 KBLIB_CONSTANT_MV is_transparent = true;
747
748 template <typename T>
749 KBLIB_NODISCARD constexpr auto operator()(const T& key,
750 HashInt offset
752 -> enable_if_t<is_hashable_v<T>, HashInt> {
753 return FNV_hash<T>{}(key, offset);
754 }
755};
756
757template <typename Key, typename Value>
758using hash_map = std::unordered_map<Key, Value, FNV_hash<>, std::equal_to<>>;
759template <typename Key, typename Value>
761 = std::unordered_multimap<Key, Value, FNV_hash<>, std::equal_to<>>;
762template <typename T, typename HashInt>
763using hash_set = std::unordered_set<T, FNV_hash<>, std::equal_to<>>;
764template <typename T, typename HashInt>
765using hash_multiset = std::unordered_set<T, FNV_hash<>, std::equal_to<>>;
766
767} // namespace kblib
768
769#endif // HASH_H
This file provides some iterators, ranges, iterator/range adapters, and operations that can be perfor...
KBLIB_CONSTANT_V is_trivial_container
Definition: hash.h:509
constexpr auto hash_tuple_impl(const Tuple &tuple, HashInt offset, std::index_sequence< I >) noexcept -> HashInt
Hash each element of a tuple. This overload is for tuples of a single type, or as the base case for t...
Definition: hash.h:617
constexpr auto all_hashable_impl(std::index_sequence< Is... >) -> bool
Definition: hash.h:645
constexpr auto all_hashable() -> bool
Definition: hash.h:677
The main namespace in which all entities from kblib are defined.
Definition: algorithm.h:44
KBLIB_CONSTANT_V is_hashable_v
Definition: hash.h:350
KBLIB_CONSTANT_V is_trivially_hashable_v
Definition: hash.h:433
constexpr auto to_pointer(P &&p) noexcept -> auto *
Gets a raw pointer out of any smart pointer or iterator you might pass in, without dereferencing it o...
Definition: iterators.h:72
std::unordered_multimap< Key, Value, FNV_hash<>, std::equal_to<> > hash_multimap
Definition: hash.h:761
typename std::enable_if< B, T >::type enable_if_t
Definition: fakestd.h:54
constexpr auto e() -> T
Definition: stats.h:468
constexpr auto to_bytes(Integral val, CharT(&dest)[sizeof(Integral)]) noexcept -> void
Definition: hash.h:80
constexpr auto FNV32a_s(const char *begin, std::size_t length, uint32_t hval=fnv::fnv_offset< std::uint32_t >::value) noexcept -> std::uint32_t
Definition: hash.h:245
constexpr auto range(Value min, Value max, Delta step=0) -> range_t< Value, Delta >
Constructs a range from beginning, end, and step amount. The range is half-open, that is min is in th...
Definition: iterators.h:621
constexpr auto FNVa(Span &&s, HashInt hval=fnv::fnv_offset< HashInt >::value) noexcept -> HashInt
A templatized generic FNVa hash function.
Definition: hash.h:147
constexpr auto visit2_nop(V &&v, F &&f, Fs &&... fs) -> void
Definition: variant.h:306
KBLIB_CONSTANT_V is_iterator_v
Definition: traits.h:424
constexpr auto length(const CharT *str) noexcept -> std::size_t
Definition: stringops.h:234
constexpr auto FNV32a_a(const char(&s)[N], std::uint32_t hval=fnv::fnv_offset< std::uint32_t >::value) noexcept -> std::uint32_t
A standard FNV32a hash function, for raw character arrays, such as string literals.
Definition: hash.h:233
constexpr int padding_bits_v< void >
Definition: hash.h:305
constexpr int padding_bits_v
Get the number of padding bits in an integral type.
Definition: hash.h:301
constexpr auto FNV32a(std::string_view s, std::uint32_t hval=fnv::fnv_offset< std::uint32_t >::value) noexcept -> std::uint32_t
A standard FNV32a hash function, for string_views.
Definition: hash.h:194
std::unordered_set< T, FNV_hash<>, std::equal_to<> > hash_multiset
Definition: hash.h:765
std::integral_constant< bool, v > bool_constant
Definition: fakestd.h:64
typename void_if< b >::type void_if_t
Definition: fakestd.h:513
constexpr auto FNVa_s(const char *begin, std::size_t length, HashInt hval=fnv::fnv_offset< HashInt >::value) noexcept -> HashInt
Definition: hash.h:208
std::unordered_set< T, FNV_hash<>, std::equal_to<> > hash_set
Definition: hash.h:763
constexpr auto to_bytes_be(Integral ival, CharT(&dest)[sizeof(Integral)]) noexcept -> void
Definition: hash.h:68
constexpr auto accumulate(InputIt first, InputIt last, T init) -> T
A constexpr version of std::accumulate.
Definition: algorithm.h:162
constexpr auto to_bytes_le(Integral ival, CharT(&dest)[sizeof(Integral)]) noexcept -> void
Definition: hash.h:56
constexpr auto FNVa_a(const CharT(&s)[N], HashInt hval=fnv::fnv_offset< HashInt >::value) noexcept -> HashInt
A templatized FNVa hash function, for raw character arrays, such as string literals.
Definition: hash.h:173
KBLIB_CONSTANT_V is_contiguous_v
Type trait to determine if a container is contiguous.
Definition: traits.h:261
constexpr endian hash_order
Definition: tdecl.h:197
std::unordered_map< Key, Value, FNV_hash<>, std::equal_to<> > hash_map
Definition: hash.h:758
constexpr auto to_unsigned(I x) -> std::make_unsigned_t< I >
Cast integral argument to corresponding unsigned type.
Definition: fakestd.h:586
Definition: bits.h:714
auto operator()(const Container &key, HashInt offset=fnv::fnv_offset< HashInt >::value) const noexcept -> HashInt
Definition: hash.h:533
constexpr auto operator()(const T &, HashInt offset=fnv::fnv_offset< HashInt >::value) const noexcept -> HashInt
Definition: hash.h:418
constexpr auto operator()(T key, HashInt offset=fnv::fnv_offset< HashInt >::value) const noexcept -> HashInt
Definition: hash.h:448
auto operator()(T key_in, HashInt offset=fnv::fnv_offset< HashInt >::value) const noexcept -> HashInt
Definition: hash.h:466
constexpr auto operator()(bool key, HashInt offset=fnv::fnv_offset< HashInt >::value) const noexcept -> HashInt
Definition: hash.h:361
constexpr auto operator()(char key, HashInt offset=fnv::fnv_offset< HashInt >::value) const noexcept -> HashInt
Definition: hash.h:375
constexpr auto operator()(signed char key, HashInt offset=fnv::fnv_offset< HashInt >::value) const noexcept -> HashInt
Definition: hash.h:389
constexpr auto operator()(const std::optional< T > &key, HashInt offset=fnv::fnv_offset< HashInt >::value) const noexcept -> HashInt
Definition: hash.h:708
constexpr auto operator()(const std::variant< Ts... > &key, HashInt offset=fnv::fnv_offset< HashInt >::value) const noexcept -> HashInt
Definition: hash.h:723
constexpr auto operator()(unsigned char key, HashInt offset=fnv::fnv_offset< HashInt >::value) const noexcept -> HashInt
Definition: hash.h:404
constexpr auto operator()(const T &key, HashInt offset=fnv::fnv_offset< HashInt >::value) -> enable_if_t< is_hashable_v< T >, HashInt >
Definition: hash.h:749
The primary template has to exist, but not be constructible, in order to be compatible with std::hash...
Definition: hash.h:334
FNV_hash(FNV_hash &&)=delete
FNV_hash()=delete
FNV_hash(const FNV_hash &)=delete
FNV_hash & operator=(const FNV_hash &)=delete
FNV_hash & operator=(FNV_hash &&)=delete
The starting value for the FNVa hash algorithm, as a type trait.
Definition: hash.h:128
KBLIB_CONSTANT_M UInt value
Definition: hash.h:129
The prime to use for the FNVa hash algorithm, as a type trait.
Definition: hash.h:108
KBLIB_CONSTANT_M UInt value
Definition: hash.h:109
Provides macros and basic templates used by the rest of kblib.
#define KBLIB_NODISCARD
This internal macro is used to provide a fallback for [[nodiscard]] in C++14.
Definition: tdecl.h:81
#define KBLIB_CONSTANT_V
Definition: tdecl.h:99
#define KBLIB_CXX20(args)
This internal macro is used to selectively use C++20 features.
Definition: tdecl.h:116
#define KBLIB_CONSTANT_M
Definition: tdecl.h:100
#define KBLIB_CONSTANT_MV
Definition: tdecl.h:101
Contains some type traits not in the standard library that are useful in the implementation of kblib.
Provides utilities for working with std::variant more expressively and more efficiently.