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_NS {
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.");
85 if (hash_order == endian::little) {
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>);
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
445template <typename T, typename HashInt>
446struct FNV_hash<
447 T, HashInt,
448 void_if_t<std::is_integral<T>::value and is_trivially_hashable_v<T>>> {
450 T key, HashInt offset = fnv::fnv_offset<HashInt>::value) const noexcept
451 -> HashInt {
452 unsigned char tmp[sizeof(T)]{};
453 to_bytes(key, tmp);
454 return FNVa_a(tmp, offset);
455 }
456};
457
464// uses std::is_pointer instead of just specializing on T* for cv pointers
465template <typename T, typename HashInt>
466struct FNV_hash<T, HashInt, void_if_t<std::is_pointer<T>::value>> {
468 T key_in, HashInt offset
469 = fnv::fnv_offset<HashInt>::value) const noexcept -> HashInt {
471 reinterpret_cast<std::uintptr_t>(key_in), offset);
472 }
473};
474
481template <typename T, typename HashInt>
482struct FNV_hash<T, HashInt,
483 void_if_t<(std::is_base_of<std::forward_iterator_tag,
484 typename std::iterator_traits<
485 T>::iterator_category>::value and
486 not std::is_pointer<T>::value and
487 not is_trivially_hashable_v<T> and
488 std::is_pointer<typename fakestd::invoke_result<
489 decltype(&T::operator->), T>::type>::value)>> {
491 T key_in, HashInt offset
492 = fnv::fnv_offset<HashInt>::value) const noexcept -> HashInt {
493 if (key_in
494 == T{}) { // avoid calling to_pointer on a value-initialized iterator
495 return FNV_hash<std::uintptr_t, HashInt>{}(0, offset);
496 } else {
498 reinterpret_cast<std::uintptr_t>(to_pointer(key_in)), offset);
499 }
500 }
501};
502
506namespace asserts {
507
508 template <typename Container>
511 and is_trivially_hashable_v<typename Container::value_type>);
512 static_assert(is_trivial_container<std::string>,
513 "kblib bug: std::string should be trivially hashable");
514
515} // namespace asserts
516
521template <typename Container, typename HashInt>
522struct FNV_hash<
523 Container, HashInt,
524 void_if_t<(
526 Container> and is_trivially_hashable_v<typename Container::value_type>)>> {
527
528 KBLIB_NODISCARD auto hash_fast(const Container& key,
529 HashInt offset) const noexcept -> HashInt {
530 return FNVa_s<HashInt>(reinterpret_cast<const char*>(key.data()),
531 key.size() * sizeof(*key.begin()), offset);
532 }
533
535 const Container& key,
536 HashInt offset = fnv::fnv_offset<HashInt>::value) const noexcept
537 -> HashInt {
538#if KBLIB_USE_CXX20
539 if (std::is_constant_evaluated()) {
540 using T = typename Container::value_type;
541 for (const auto& e : key) {
542 offset = FNV_hash<T>{}(e, offset);
543 }
544 } else {
545 return hash_fast(key, offset);
546 }
547#else
548 return hash_fast(key, offset);
549#endif
550 }
551};
552
561template <typename T, typename HashInt>
562struct FNV_hash<
563 T, HashInt,
564 void_if_t<not is_contiguous_v<T> and not std::is_integral<T>::value
565 and not std::is_pointer<T>::value
566 and is_trivially_hashable_v<T>>> {
567 KBLIB_NODISCARD KBLIB_CXX20(constexpr) auto operator()(
568 T key, HashInt offset = fnv::fnv_offset<HashInt>::value) const noexcept
569 -> HashInt {
570#if KBLIB_USE_CXX20
571 auto tmp = std::bit_cast<std::array<char, sizeof(T)>>(key);
572 return FNVa_s(tmp.data(), tmp.size(), offset);
573#else
574 char tmp[sizeof(T)];
575 std::memcpy(tmp, &key, sizeof(T));
576 return FNVa_a(tmp, offset);
577#endif
578 }
579};
580
585template <typename Container, typename HashInt>
586struct FNV_hash<
587 Container, HashInt,
588 void_if_t<
589 value_detected<Container>::value
590 and is_hashable_v<
591 value_detected_t<Container>> and not hash_detected<Container>::value
592 and is_iterable<Container>::value
593 and not (is_contiguous<Container>::value
594 and is_trivially_hashable_v<typename Container::value_type>)
595 and not is_iterator_v<Container>>> {
597 const Container& key,
598 HashInt offset = fnv::fnv_offset<HashInt>::value) const noexcept
599 -> HashInt {
600 using Elem = typename Container::value_type;
601 return std::accumulate(cbegin(key), cend(key), offset,
602 [](HashInt offset_, const Elem& elem) {
603 return FNV_hash<Elem, HashInt>{}(elem, offset_);
604 });
605 }
606};
607
612namespace detail_hash {
613
622 template <typename Tuple, typename HashInt, std::size_t I>
623 constexpr auto hash_tuple_impl(const Tuple& tuple, HashInt offset,
624 std::index_sequence<I>) noexcept -> HashInt {
626 std::get<I>(tuple), offset);
627 }
628
637 template <typename Tuple, typename HashInt, std::size_t I, std::size_t I2,
638 std::size_t... Is>
639 constexpr auto hash_tuple_impl(const Tuple& tuple, HashInt offset,
640 std::index_sequence<I, I2, Is...>) noexcept
641 -> HashInt {
642 HashInt first_hash
644 std::get<I>(tuple), offset);
645 return hash_tuple_impl(tuple, first_hash,
646 std::index_sequence<I2, Is...>{});
647 }
648
649#if KBLIB_USE_CXX17
650 template <typename Tuple, std::size_t... Is>
651 constexpr auto all_hashable_impl(std::index_sequence<Is...>) -> bool {
652 return (...
653 and is_hashable_v<typename std::tuple_element<Is, Tuple>::type>);
654 }
655#else
656
657 template <typename Tuple, typename IS>
658 struct all_hashable_impl_t;
659
660 template <typename Tuple, std::size_t I, std::size_t... Is>
661 struct all_hashable_impl_t<Tuple, std::index_sequence<I, Is...>>
662 : bool_constant<(
663 is_hashable_v<
664 typename std::tuple_element<I, Tuple>::
665 type> and all_hashable_impl_t<Tuple, std::index_sequence<Is...>>::value)> {
666 };
667
668 template <typename Tuple, std::size_t I>
669 struct all_hashable_impl_t<Tuple, std::index_sequence<I>>
671 is_hashable_v<typename std::tuple_element<I, Tuple>::type>> {};
672
673 template <typename Tuple, std::size_t... Is>
674 constexpr auto all_hashable_impl(std::index_sequence<Is...>) -> bool {
675 return all_hashable_impl_t<Tuple, std::index_sequence<Is...>>::value;
676 }
677#endif
678
679 template <
680 typename Tuple,
681 typename std::enable_if<(std::tuple_size<Tuple>::value > 0u), int>::type
682 = 0>
683 constexpr auto all_hashable() -> bool {
684 return all_hashable_impl<Tuple>(
685 std::make_index_sequence<std::tuple_size<Tuple>::value>{});
686 }
687
688} // namespace detail_hash
689
694template <typename Tuple, typename HashInt>
695struct FNV_hash<Tuple, HashInt,
698 Tuple> and (std::tuple_size<Tuple>::value > 0u)
699 and not is_linear_container_v<Tuple>>> {
701 const Tuple& key,
702 HashInt offset = fnv::fnv_offset<HashInt>::value) const noexcept
703 -> HashInt {
705 key, offset,
706 std::make_index_sequence<std::tuple_size<Tuple>::value>{});
707 }
708};
709
710#if KBLIB_USE_CXX17
711
712template <typename T, typename HashInt>
713struct FNV_hash<std::optional<T>, HashInt, void> {
715 const std::optional<T>& key,
716 HashInt offset = fnv::fnv_offset<HashInt>::value) const noexcept
717 -> HashInt {
718 if (key) {
719 return FNV_hash<T, HashInt>{}(key.value(), offset);
720 } else {
721 return FNV_hash<std::nullopt_t, HashInt>{}(std::nullopt, offset);
722 }
723 }
724};
725
726template <typename... Ts, typename HashInt>
727struct FNV_hash<std::variant<Ts...>, HashInt,
728 void_if_t<detail_hash::all_hashable<std::tuple<Ts...>>()>> {
730 const std::variant<Ts...>& key,
731 HashInt offset = fnv::fnv_offset<HashInt>::value) const noexcept
732 -> HashInt {
733 // Variant index is hashed alongside the value
734 offset = FNV_hash<HashInt>{}(key.index(), offset);
735 // visit2_nop does nothing when the variant is valueless_by_exception
736 kblib::visit2_nop(key, [&](auto& V) {
737 offset = FNV_hash<typename std::remove_reference<decltype(V)>::type,
738 HashInt>{}(V, offset);
739 });
740 return offset;
741 }
742};
743
744#endif
745
750template <typename HashInt>
751struct FNV_hash<void, HashInt, void> {
752 KBLIB_CONSTANT_MV is_transparent = true;
753
754 template <typename T>
756 const T& key,
757 HashInt offset = fnv::fnv_offset<HashInt>::value) const noexcept
758 -> enable_if_t<is_hashable_v<T>, HashInt> {
759 return FNV_hash<T>{}(key, offset);
760 }
761};
762
763template <typename Key, typename Value>
764using hash_map = std::unordered_map<Key, Value, FNV_hash<>, std::equal_to<>>;
765template <typename Key, typename Value>
767 = std::unordered_multimap<Key, Value, FNV_hash<>, std::equal_to<>>;
768template <typename T, typename HashInt>
769using hash_set = std::unordered_set<T, FNV_hash<>, std::equal_to<>>;
770template <typename T, typename HashInt>
771using hash_multiset = std::unordered_set<T, FNV_hash<>, std::equal_to<>>;
772
773} // namespace KBLIB_NS
774
775#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:510
constexpr auto all_hashable_impl(std::index_sequence< Is... >) -> bool
Definition: hash.h:651
constexpr auto all_hashable() -> bool
Definition: hash.h:683
constexpr auto hash_tuple_impl(const Tuple &tuple, HashInt offset, std::index_sequence< I, I2, Is... >) noexcept -> HashInt
Hash each element of a tuple. This overload is for tuples of at least 2 elements.
Definition: hash.h:639
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:767
typename std::enable_if< B, T >::type enable_if_t
Definition: fakestd.h:61
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:771
std::integral_constant< bool, v > bool_constant
Definition: fakestd.h:71
typename void_if< b >::type void_if_t
Definition: fakestd.h:520
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:769
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:227
std::unordered_map< Key, Value, FNV_hash<>, std::equal_to<> > hash_map
Definition: hash.h:764
constexpr auto to_unsigned(I x) -> std::make_unsigned_t< I >
Cast integral argument to corresponding unsigned type.
Definition: fakestd.h:592
Definition: bits.h:721
constexpr auto operator()(const Container &key, HashInt offset=fnv::fnv_offset< HashInt >::value) const noexcept -> HashInt
Definition: hash.h:534
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:449
auto operator()(T key_in, HashInt offset=fnv::fnv_offset< HashInt >::value) const noexcept -> HashInt
Definition: hash.h:467
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:714
constexpr auto operator()(const std::variant< Ts... > &key, HashInt offset=fnv::fnv_offset< HashInt >::value) const noexcept -> HashInt
Definition: hash.h:729
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) const noexcept -> enable_if_t< is_hashable_v< T >, HashInt >
Definition: hash.h:755
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
The prime to use for the FNVa hash algorithm, as a type trait.
Definition: hash.h:108
Provides macros and basic templates used by the rest of kblib.
#define KBLIB_NS
Definition: tdecl.h:113
#define KBLIB_NODISCARD
This internal macro is used to provide a fallback for [[nodiscard]] in C++14.
Definition: tdecl.h:129
#define KBLIB_CONSTANT_V
Definition: tdecl.h:138
#define KBLIB_CXX20(args)
This internal macro is used to selectively use C++20 features.
Definition: tdecl.h:96
#define KBLIB_CONSTANT_M
Definition: tdecl.h:139
#define KBLIB_CONSTANT_MV
Definition: tdecl.h:140
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.