kblib 0.2.3
General utilities library for modern C++
bits.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
31#ifndef KBLIB_BITS_H
32#define KBLIB_BITS_H
33
34#include <algorithm>
35#include <array>
36#include <bitset>
37#include <limits>
38#include <memory>
39#include <utility>
40#include <vector>
41
42#include <iostream>
43
44#include "fakestd.h"
45#include "simple.h"
46#include "stats.h"
47#include "tdecl.h"
48#include "traits.h"
49
50namespace KBLIB_NS {
51
52template <typename Int>
53constexpr int bits_of = std::numeric_limits<Int>::digits;
54
55#if KBLIB_USE_CXX17
56
57namespace detail_bits {
58
59 template <typename Key, typename Value>
60 class trie_node {
61 std::unique_ptr<std::array<trie_node, 4>> children;
62 unsigned char storage[sizeof(Value)]{};
63 bool exists = false;
64
65 template <typename... Args>
66 auto create(Args&&... args) noexcept(
67 std::is_nothrow_constructible<Value, Args...>::value) -> Value& {
68 clear();
69 // This variable must exist for exception safety. exists should not be
70 // set to true if an exception is thrown.
71 auto v = *new (storage) Value(args...);
72 exists = true;
73 return *v;
74 }
75
76 auto clear() noexcept -> void {
77 if (exists) {
78 get()->~Value();
79 }
80 return;
81 }
82
83 KBLIB_NODISCARD auto get() noexcept -> Value& {
84 assert(exists);
85 return *reinterpret_cast<Value*>(storage);
86 }
87 KBLIB_NODISCARD auto get() const noexcept -> const Value& {
88 assert(exists);
89 return *reinterpret_cast<Value*>(storage);
90 }
91 };
92
93} // namespace detail_bits
94/*
95template <typename Key, typename Value>
96class bit_trie {
97 public:
98 using value_type = Value;
99 using key_type = Key;
100 using mapped_type = Value;
101
102 static_assert(std::is_integral<key_type>::value,
103 "key_type must be an integral type.");
104 static_assert(std::is_nothrow_destructible<mapped_type>::value,
105 "mapped_type must be nothrow destructible.");
106
107 void insert(key_type, const mapped_type&);
108 void insert(key_type, mapped_type&&);
109
110 private:
111 std::array<detail_bits::trie_node, bits_of<key_type>> roots;
112};//*/
113
114template <typename Key, Key key_range, typename Value>
116 public:
117 struct key_type {
119 std::uint16_t bits : filg2(key_range);
120 };
121
122 using value_type = Value;
123 using mapped_type = Value;
129 using const_pointer = const value_type*;
130
131 template <typename V>
132 class iterator_t;
133
136 using reverse_iterator = std::reverse_iterator<iterator>;
137 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
138
139 using bitset_type = std::bitset<bits_of<Key>>;
140
141 static_assert(std::is_integral<Key>::value, "Key must be an integral type.");
142 static_assert(std::is_unsigned<Key>::value, "Key must be unsigned.");
143 static_assert(std::is_nothrow_destructible<mapped_type>::value,
144 "mapped_type must be nothrow destructible.");
145
146 KBLIB_NODISCARD auto at(key_type key) const noexcept(false)
147 -> const_reference {
148 if (empty()) {
149 throw std::out_of_range("searched in an empty compact_bit_trie");
150 }
151 if (key.bits > bits_of<Key>) {
152 throw std::invalid_argument("key prefix longer than key length");
153 }
154 size_type node = 1;
155 const bitset_type search = key.prefix;
156 int idx = 0;
157 while (node and idx < key.bits) {
158 if (auto val = storage[node].val) {
159 return values[val];
160 } else {
161 node = storage[node].children[search[idx++]];
162 }
163 }
164 throw std::out_of_range("key not found in compact_bit_trie");
165 }
166
167 KBLIB_NODISCARD auto at(key_type key) noexcept(false) -> reference {
168 if (empty()) {
169 throw std::out_of_range("searched in an empty compact_bit_trie");
170 }
171 if (key.bits > bits_of<Key>) {
172 throw std::invalid_argument("key prefix longer than key length");
173 }
174 size_type node = 1;
175 const bitset_type search = key.prefix;
176 int idx = 0;
177 while (node and idx < key.bits) {
178 if (auto val = storage[node].val) {
179 return values[val];
180 } else {
181 node = storage[node].children[search[idx++]];
182 }
183 }
184 throw std::out_of_range("key not found in compact_bit_trie");
185 }
186
187 KBLIB_NODISCARD auto find_deep(key_type key, size_type depth = -1) const
188 noexcept(false) -> const_reference {
189 if (empty()) {
190 throw std::out_of_range("searched in an empty compact_bit_trie");
191 }
192 if (key.bits > bits_of<Key>) {
193 throw std::invalid_argument("key prefix longer than key length");
194 }
195 size_type node = 1;
196 size_type found = 0;
197 const bitset_type search = key.prefix;
198 int idx = 0;
199 while (node and idx < key.bits) {
200 if (auto val = storage[node].val) {
201 found = val;
202 if (depth--) {
203 break;
204 }
205 }
206 node = storage[node].children[search[idx++]];
207 }
208 if (found) {
209 return values[found];
210 } else {
211 throw std::out_of_range("key not found in compact_bit_trie");
212 }
213 }
214
216 size_type depth = -1) noexcept(false)
217 -> reference {
218 if (empty()) {
219 throw std::out_of_range("searched in an empty compact_bit_trie");
220 }
221 if (key.bits > bits_of<Key>) {
222 throw std::invalid_argument("key prefix longer than key length");
223 }
224 size_type node = 1;
225 size_type found = 0;
226 const bitset_type search = key.prefix;
227 int idx = 0;
228 while (node and idx < key.bits) {
229 if (auto val = storage[node].val) {
230 found = val;
231 if (depth--) {
232 break;
233 }
234 }
235 node = storage[node].children[search[idx++]];
236 }
237 if (found) {
238 return values[found];
239 } else {
240 throw std::out_of_range("key not found in compact_bit_trie");
241 }
242 }
243
244 KBLIB_NODISCARD auto empty() const noexcept -> bool {
245 return values.empty();
246 }
247
248 template <typename... Ts>
249 auto emplace(key_type key, Ts&&... args) -> bool {
250 size_type node = get_storage_node_for(key);
251 if (auto& v = storage[node].val; v != max) {
252 return false;
253 } else {
254 values.emplace_back(std::forward<Ts>(args)...);
255 v = static_cast<size_type>(values.size() - 1);
256 return true;
257 }
258 }
259
260 auto insert(key_type key, const value_type& value) -> bool {
261 return emplace(key, value);
262 }
263 auto insert(key_type key, value_type&& value) -> bool {
264 return emplace(key, std::move(value));
265 }
266
267 auto insert_or_assign(key_type key, const value_type& value) -> reference {
268 size_type node = get_storage_node_for(key);
269 auto& v = storage[node].val;
270 if (v != -1) {
271 values.push_back(value);
272 v = static_cast<size_type>(values.size() - 1);
273 } else {
274 values[v] = value;
275 }
276 return values[v];
277 }
278
280 size_type node = get_storage_node_for(key);
281 auto& v = storage[node].val;
282 if (v != -1) {
283 values.push_back(std::move(value));
284 v = static_cast<size_type>(values.size() - 1);
285 } else {
286 values[v] = std::move(value);
287 }
288 return values[v];
289 }
290
291 bool erase(key_type key);
292 bool prune(key_type prefix);
293 auto clear() -> void {
294 storage.clear();
295 values.clear();
296 }
297
298 KBLIB_NODISCARD auto size() const noexcept -> size_type {
299 return static_cast<size_type>(values.size());
300 }
301
302 KBLIB_NODISCARD auto memory_use() const noexcept -> std::size_t {
303 return storage.capacity() * sizeof(inline_node)
304 + values.size() * sizeof(Value);
305 }
306
307 auto shrink_to_fit() -> void {
308 storage.shrink_to_fit();
309 values.shrink_to_fit();
310 }
311
312 private:
313 struct inline_node {
314 size_type children[2];
315 size_type parent;
316 size_type val;
317 };
318 std::vector<inline_node> storage;
319 std::vector<Value> values;
320
321 auto do_init() -> void {
322 if (storage.size() < 2) {
323 storage.resize(2);
324 storage[0] = {};
325 storage[1] = {};
326 }
327 }
328
329 KBLIB_NODISCARD auto get_storage_node_for(key_type key) -> size_type {
330 if (key.bits > bits_of<Key>) {
331 throw std::invalid_argument("key prefix longer than key length");
332 }
333 const bitset_type search = key.prefix;
334 size_type node = 1;
335 do_init();
336 for (std::size_t i : range<std::size_t>(key.bits - 1)) {
337 if (auto n = storage[node].children[std::as_const(search)[i]]) {
338 node = n;
339 } else {
340 storage.push_back({{0, 0}, node, max});
341 node = static_cast<size_type>(storage.size() - 1);
342 storage[node].children[std::as_const(search)[i]] = node;
343 }
344 }
345 return node;
346 }
347
348 public:
349 template <typename V>
351 public:
352 using value_type = V;
353 using pointer = V*;
354 using reference = V&;
356 using iterator_category = std::bidirectional_iterator_tag;
357
358 iterator_t() = default;
360 : tree_ptr{&range.storage}
361 , values_ptr{&range.values}
362 , node{0} {}
363
364 auto operator*() const noexcept -> reference {
365 return (*values_ptr)[(*tree_ptr)[node].val];
366 }
367 auto operator->() const noexcept -> pointer {
368 return std::addressof((*values_ptr)[(*tree_ptr)[node].val]);
369 }
371
372 private:
374 : iterator_t(range) {
375 node = n_;
376 }
377
378 const std::vector<inline_node>* tree_ptr{};
379 const std::vector<Value>* values_ptr{};
380 size_type node{};
381 };
382};
383
394constexpr inline auto memswap(unsigned char* A, unsigned char* B,
395 std::size_t size) noexcept -> void {
396 for (auto i : range(size)) {
397 (swap)(A[i], B[i]);
398 }
399 return;
400}
401
412inline auto memswap(void* A, void* B, std::size_t size) noexcept -> void {
413 auto Ab = static_cast<unsigned char*>(A);
414 auto Bb = static_cast<unsigned char*>(B);
415 memswap(Ab, Bb, size);
416 return;
417}
418
419#endif
420
436template <unsigned offset, unsigned size, typename Storage>
437struct bitfield {
438 auto operator()() const noexcept -> Storage {
439 return (get() >> offset) & ((1u << size) - 1);
440 }
441 auto operator()(const Storage val) noexcept -> Storage {
442 // Clear the bits for this field
443 get() &= ~(((1u << size) - 1) << offset);
444 // Set the field
445 get() |= (val & ((1u << size) - 1)) << offset;
446 return val;
447 }
448 operator Storage() const noexcept { return (*this)(); }
449 auto operator=(Storage val) noexcept -> Storage { return (*this)(val); }
450
451 // allowed by pointer-interconvertibility when placed in a union
452 Storage& get() noexcept { return *reinterpret_cast<Storage*>(this); }
453 const Storage& get() const noexcept {
454 return *reinterpret_cast<const Storage*>(this);
455 }
456 // ensure that there is an object for pointer-interconvertibility to find
457 Storage raw_;
458 // Is this a good idea?
459 auto operator&() -> void = delete;
460};
461
462namespace detail_bits {
463
472 template <typename Parent, typename ReturnT,
473 ReturnT (Parent::*Set)(ReturnT) noexcept,
474 ReturnT (Parent::*Get)() const noexcept>
476 Parent* p;
477 constexpr auto operator=(ReturnT val) noexcept -> ReturnT {
478 return (p->*Set)(val);
479 }
480 constexpr operator ReturnT() const noexcept { return (p->*Get)(); }
481 };
482
483} // namespace detail_bits
484
491#define KBLIB_INTERNAL_BITFIELD_MACRO(offset, size, name, raw) \
492 static_assert(offset >= 0 and size > 0, \
493 "BITFIELD cannot have negative offset or size"); \
494 \
495 private: \
496 constexpr auto name##_get_impl() const noexcept->decltype(raw) { \
497 return (raw >> kblib::to_unsigned(offset)) \
498 & ((decltype(raw)(1) << kblib::to_unsigned(size)) - 1u); \
499 } \
500 \
501 public: \
502 KBLIB_NODISCARD constexpr auto name() const noexcept->decltype(raw) { \
503 return name##_get_impl(); \
504 } \
505 \
506 private: \
507 constexpr auto name##_set_impl(const decltype(raw) val) noexcept->decltype( \
508 raw) { \
509 /* Clear the bits for this field */ \
510 raw &= ~(((decltype(raw)(1) << kblib::to_unsigned(size)) - 1u) \
511 << kblib::to_unsigned(offset)); \
512 /* Set the field */ \
513 raw |= (val & ((decltype(raw)(1) << kblib::to_unsigned(size)) - 1u)) \
514 << kblib::to_unsigned(offset); \
515 return val; \
516 } \
517 \
518 public: \
519 constexpr auto name(const decltype(raw) val) noexcept->decltype(raw) { \
520 return name##_set_impl(val); \
521 } \
522 \
523 KBLIB_NODISCARD constexpr auto name() noexcept->auto { \
524 using Parent = std::remove_pointer<decltype(this)>::type; \
525 return kblib::detail_bits::bitfield_proxy<Parent, decltype(raw), \
526 &Parent::name##_set_impl, \
527 &Parent::name##_get_impl>{ \
528 this}; \
529 } \
530 \
531 template <decltype(raw) val, decltype(raw) basis = 0> \
532 constexpr static decltype(raw) set_##name##_v \
533 = (basis \
534 & ~(((decltype(raw)(1) << kblib::to_unsigned(size)) - 1u) \
535 << kblib::to_unsigned(offset))) \
536 | (val & ((decltype(raw)(1) << kblib::to_unsigned(size)) - 1u)) \
537 << kblib::to_unsigned(offset); \
538 \
539 template <decltype(raw) basis> \
540 constexpr static decltype(raw) get_##name##_v \
541 = (basis >> kblib::to_unsigned(offset)) \
542 & ((decltype(raw)(1) << kblib::to_unsigned(size)) - 1u); \
543 constexpr static std::size_t name##_shift_v = offset; \
544 constexpr static std::size_t name##_width_v = size;
545
546namespace detail_bits {
547
548 template <typename Type, typename Storage>
549 struct pun_proxy {
550 Storage& base;
551 auto operator=(const Type val) noexcept -> pun_proxy& {
552 std::memcpy(&base, &val, sizeof val);
553 return *this;
554 }
555 operator Type() const noexcept {
556 Type ret;
557 std::memcpy(&ret, &base, sizeof ret);
558 return ret;
559 }
560 };
561
562 template <typename Type, typename Storage>
564 Storage& base;
565 Type data;
566 bool dirty = false;
567 operator Type&() noexcept {
568 if (dirty) {
569 std::memcpy(&base, &data, sizeof data);
570 }
571 dirty = true;
572 return data;
573 }
574 operator const Type&() const noexcept {
575 if (dirty) {
576 std::memcpy(&base, &data, sizeof data);
577 }
578 return data;
579 }
581 if (dirty) {
582 std::memcpy(&base, &data, sizeof data);
583 }
584 }
589 };
590
591 template <typename T>
593 using type = T;
594 };
595 template <typename T, std::size_t N>
597 using type = std::array<T, N>;
598 };
599 template <typename T>
601 using type = std::array<T, 0>;
602 };
603
604 template <typename T, std::size_t S>
606 using type = T;
607 };
608 template <typename T, std::size_t N, std::size_t S>
610 using type = std::array<T, N>;
611 };
612 template <typename T, std::size_t S>
614 using type = std::array<T, S / sizeof(T)>;
615 };
616
617 template <typename P, typename Type, std::size_t S, std::size_t,
618 bool aliases
619 = is_aliasing_type_v<typename std::remove_extent<Type>::type>>
620 struct pun_el {
621
623
624 static_assert(std::is_trivially_copyable<type>::value,
625 "Type must be trivially copyable");
626
627 KBLIB_NODISCARD auto get() noexcept -> auto {
628 return pun_proxy<type, decltype(P::raw)>{static_cast<P*>(this)->raw};
629 }
630 KBLIB_NODISCARD auto get() const noexcept -> auto {
631 return pun_proxy<const type, const decltype(P::raw)>{
632 static_cast<const P*>(this)->raw};
633 }
634 };
635
636 template <typename P, typename Type, std::size_t S, std::size_t I>
637 struct pun_el<P, Type[S], S, I, true> {
638 using type = Type[S];
639
640 KBLIB_NODISCARD auto get() noexcept -> decltype(auto) {
641 return reinterpret_cast<type&>(static_cast<P*>(this)->raw);
642 }
643 KBLIB_NODISCARD auto get() const noexcept -> decltype(auto) {
644 return reinterpret_cast<const type&>(static_cast<const P*>(this)->raw);
645 }
646 };
647
648 template <typename P, typename Type, std::size_t S, std::size_t I>
649 struct pun_el<P, Type[], S, I, true> {
650 using type = Type[S];
651
652 KBLIB_NODISCARD auto get() noexcept -> decltype(auto) {
653 return reinterpret_cast<type&>(static_cast<P*>(this)->raw);
654 }
655 KBLIB_NODISCARD auto get() const noexcept -> decltype(auto) {
656 return reinterpret_cast<const type&>(static_cast<const P*>(this)->raw);
657 }
658 };
659
660 template <std::size_t S, typename I_S, typename... Types>
662
663 template <std::size_t S, std::size_t... Is, typename... Types>
664 struct punner_impl<S, std::index_sequence<Is...>, Types...>
665 : pun_el<punner_impl<S, std::index_sequence<Is...>, Types...>, Types, S,
666 Is>... {
667
668 alignas(std::max({alignof(typename std::remove_extent<
669 Types>::type)...})) unsigned char raw[S]{};
670 };
671
672 template <typename... Types>
673 constexpr std::size_t max_size
674 = std::max({sizeof(typename array_filter<Types>::type)...});
675
676} // namespace detail_bits
677
678template <typename... Types>
679struct punner
680 : private detail_bits::punner_impl<detail_bits::max_size<Types...>,
681 std::index_sequence_for<Types...>,
682 Types...> {
683 private:
684 constexpr static std::size_t storage_size = detail_bits::max_size<Types...>;
685 using impl_t
686 = detail_bits::punner_impl<storage_size,
687 std::index_sequence_for<Types...>, Types...>;
688 using tuple_t = std::tuple<Types...>;
689 template <std::size_t I>
690 using r_element_t = typename std::tuple_element<I, tuple_t>::type;
691
692 static_assert(std::is_standard_layout<impl_t>::value, "");
693
694 public:
695 template <std::size_t I>
697 template <std::size_t I>
698 using element_t = typename base_t<I>::type;
699
700 template <std::size_t I>
701 KBLIB_NODISCARD auto get() & noexcept -> decltype(auto) {
702 static_assert(std::is_base_of<base_t<I>, impl_t>::value, "");
703 return static_cast<base_t<I>&>(*this).get();
704 }
705 template <std::size_t I>
706 KBLIB_NODISCARD auto get() const& noexcept -> decltype(auto) {
707 return static_cast<const base_t<I>&>(*this).get();
708 }
709 template <std::size_t I>
710 KBLIB_NODISCARD auto get() && noexcept -> decltype(auto) {
711 return static_cast<base_t<I>&&>(*this).get();
712 }
713 template <std::size_t I>
714 KBLIB_NODISCARD auto get() const&& noexcept -> decltype(auto) {
715 return static_cast<const base_t<I>&&>(*this).get();
716 }
717};
718
719} // namespace KBLIB_NS
720
721namespace std {
722
723template <std::size_t I, typename... Types>
724struct tuple_element<I, kblib::punner<Types...>> {
725 using type = typename kblib::punner<Types...>::template element_t<I>;
726};
727
728template <typename... Types>
729struct tuple_size<kblib::punner<Types...>>
730 : public std::integral_constant<std::size_t, sizeof...(Types)> {};
731
732} // namespace std
733
734namespace KBLIB_NS {
735
736template <std::size_t I, typename... Types>
737KBLIB_NODISCARD auto get(punner<Types...>& p) noexcept -> decltype(auto) {
738 return p.template get<I>();
739}
740template <std::size_t I, typename... Types>
741KBLIB_NODISCARD auto get(const punner<Types...>& p) noexcept -> decltype(auto) {
742 return p.template get<I>();
743}
744template <std::size_t I, typename... Types>
745KBLIB_NODISCARD auto get(punner<Types...>&& p) noexcept -> decltype(auto) {
746 return p.template get<I>();
747}
748template <std::size_t I, typename... Types>
749KBLIB_NODISCARD auto get(const punner<Types...>&& p) noexcept
750 -> decltype(auto) {
751 return p.template get<I>();
752}
753
754#if KBLIB_USE_CXX17
755template <typename Type, auto Storage>
757 private:
758 using sptr_t = decltype(Storage);
759 using class_t = kblib::class_t<Storage>;
760 using member_t = kblib::member_of_t<sptr_t>;
763
764 static_assert(sizeof(Type) <= sizeof(member_t),
765 "Type will not fit in the provided storage.");
766 static_assert(std::is_trivially_copyable_v<Type>,
767 "Type must be trivially copyable.");
768 static_assert(
769 std::is_trivially_copyable_v<std::remove_all_extents_t<member_t>>,
770 "Storage type must be trivially copyable.");
771
772 KBLIB_NODISCARD auto base() noexcept -> member_t& {
773 return reinterpret_cast<class_t*>(this)->*Storage;
774 }
775 KBLIB_NODISCARD auto base() const noexcept -> const member_t& {
776 return reinterpret_cast<const class_t*>(this)->*Storage;
777 }
778
779 public:
780 KBLIB_NODISCARD auto operator()() const noexcept -> const_proxy_t {
781 return {base()};
782 }
783 auto operator()(const Type val) noexcept -> proxy_t {
784 std::memcpy(&base(), &val, sizeof val);
785 return {base()};
786 }
787 operator Type() const noexcept { return (*this)(); }
788 auto operator=(const Type val) noexcept -> proxy_t { return (*this)(val); }
789};
790
791template <typename Type, std::size_t N, auto Storage>
792class union_pun<Type[N], Storage> {
793 private:
794 using class_t = kblib::class_t<Storage>;
795 using member_t = kblib::member_t<class_t, Storage>;
796 using type = std::array<Type, N>;
799
800 static_assert(sizeof(type) <= sizeof(member_t),
801 "Type will not fit in the provided storage.");
802 static_assert(std::is_trivially_copyable_v<type>,
803 "Type must be trivially copyable.");
804 static_assert(
805 std::is_trivially_copyable_v<std::remove_all_extents_t<member_t>>,
806 "Storage type must be trivially copyable.");
807
808 KBLIB_NODISCARD auto base() noexcept -> member_t& {
809 return reinterpret_cast<class_t*>(this)->*Storage;
810 }
811 KBLIB_NODISCARD auto base() const noexcept -> const member_t& {
812 return reinterpret_cast<const class_t*>(this)->*Storage;
813 }
814
815 public:
816 KBLIB_NODISCARD auto operator()() const noexcept -> const_proxy_t {
817 return {base()};
818 }
819 auto operator()(const Type (&val)[N]) noexcept -> proxy_t {
820 std::memcpy(&base(), &val, sizeof val);
821 return {base()};
822 }
823 operator type() const noexcept { return (*this)(); }
824 auto operator=(const Type (&val)[N]) noexcept -> proxy_t {
825 return (*this)(val);
826 }
827};
828#endif
829
830} // namespace KBLIB_NS
831
832#endif // KBLIB_BITS_H
833
834#if KBLIB_DEF_MACROS and not defined(BITFIELD)
863#define BITFIELD(offset, size, name, raw) \
864 KBLIB_INTERNAL_BITFIELD_MACRO(offset, size, name, raw)
865#endif // KBLIB_DEF_MACROS and not defined(BITFIELD)
iterator_t(const compact_bit_trie &range)
Definition: bits.h:359
compact_bit_trie::difference_type difference_type
Definition: bits.h:355
auto operator->() const noexcept -> pointer
Definition: bits.h:367
auto operator++() -> iterator_t
Definition: bits.h:370
auto operator*() const noexcept -> reference
Definition: bits.h:364
std::bidirectional_iterator_tag iterator_category
Definition: bits.h:356
auto clear() -> void
Definition: bits.h:293
auto memory_use() const noexcept -> std::size_t
Definition: bits.h:302
auto insert(key_type key, const value_type &value) -> bool
Definition: bits.h:260
const value_type * const_pointer
Definition: bits.h:129
value_type * pointer
Definition: bits.h:128
auto at(key_type key) const noexcept(false) -> const_reference
Definition: bits.h:146
value_type & reference
Definition: bits.h:126
auto at(key_type key) noexcept(false) -> reference
Definition: bits.h:167
uint_smallest_t< key_range > size_type
Definition: bits.h:124
auto emplace(key_type key, Ts &&... args) -> bool
Definition: bits.h:249
auto empty() const noexcept -> bool
Definition: bits.h:244
auto insert_or_assign(key_type key, const value_type &value) -> reference
Definition: bits.h:267
auto insert_or_assign(key_type key, value_type &&value) -> reference
Definition: bits.h:279
auto size() const noexcept -> size_type
Definition: bits.h:298
bool prune(key_type prefix)
std::bitset< bits_of< Key > > bitset_type
Definition: bits.h:139
std::reverse_iterator< iterator > reverse_iterator
Definition: bits.h:136
auto find_deep(key_type key, size_type depth=-1) const noexcept(false) -> const_reference
Definition: bits.h:187
int_smallest_t< key_range > difference_type
Definition: bits.h:125
bool erase(key_type key)
const value_type & const_reference
Definition: bits.h:127
auto insert(key_type key, value_type &&value) -> bool
Definition: bits.h:263
auto find_deep(key_type key, size_type depth=-1) noexcept(false) -> reference
Definition: bits.h:215
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: bits.h:137
auto shrink_to_fit() -> void
Definition: bits.h:307
auto operator()() const noexcept -> const_proxy_t
Definition: bits.h:816
auto operator=(const Type(&val)[N]) noexcept -> proxy_t
Definition: bits.h:824
auto operator()(const Type(&val)[N]) noexcept -> proxy_t
Definition: bits.h:819
auto operator()(const Type val) noexcept -> proxy_t
Definition: bits.h:783
auto operator=(const Type val) noexcept -> proxy_t
Definition: bits.h:788
auto operator()() const noexcept -> const_proxy_t
Definition: bits.h:780
This header provides some features of C++17 <type_traits> and other headers for C++14,...
constexpr std::size_t max_size
Definition: bits.h:674
constexpr auto size(const C &c) -> decltype(c.size())
Definition: fakestd.h:373
constexpr struct kblib::nums::max_t max
The main namespace in which all entities from kblib are defined.
Definition: algorithm.h:44
auto memswap(void *A, void *B, std::size_t size) noexcept -> void
Swaps memory ranges.
Definition: bits.h:412
struct kblib::@0 swap
typename int_smallest< I >::type int_smallest_t
Definition: simple.h:201
constexpr auto filg2(const std::bitset< std::numeric_limits< std::uintmax_t >::digits > val) noexcept -> int
Floored integer binary logarithm. Returns floor(lb(val)).
Definition: simple.h:166
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
typename member_of< T >::type member_of_t
Definition: traits.h:297
constexpr int bits_of
Definition: bits.h:53
auto get(const punner< Types... > &&p) noexcept -> decltype(auto)
Definition: bits.h:749
typename uint_smallest< I >::type uint_smallest_t
Definition: simple.h:198
Definition: bits.h:721
Provides general utilities which do not fit in any more specific header.
Provides numerical and mathematical utilities.
Implements a bitfield abstraction. May be used in a union with other bitfields.
Definition: bits.h:437
const Storage & get() const noexcept
Definition: bits.h:453
Storage raw_
Definition: bits.h:457
auto operator&() -> void=delete
auto operator()(const Storage val) noexcept -> Storage
Definition: bits.h:441
Storage & get() noexcept
Definition: bits.h:452
auto operator()() const noexcept -> Storage
Definition: bits.h:438
auto operator=(Storage val) noexcept -> Storage
Definition: bits.h:449
std::array< T, S/sizeof(T)> type
Definition: bits.h:614
array_pun_proxy & operator=(const array_pun_proxy &)=delete
array_pun_proxy(array_pun_proxy &&)=delete
array_pun_proxy & operator=(array_pun_proxy &&)=delete
array_pun_proxy(const array_pun_proxy &)=delete
A proxy reference type for BITFIELD-declared bitfields.
Definition: bits.h:475
constexpr auto operator=(ReturnT val) noexcept -> ReturnT
Definition: bits.h:477
auto get() const noexcept -> decltype(auto)
Definition: bits.h:655
auto get() noexcept -> decltype(auto)
Definition: bits.h:652
auto get() noexcept -> decltype(auto)
Definition: bits.h:640
auto get() const noexcept -> decltype(auto)
Definition: bits.h:643
auto get() const noexcept -> auto
Definition: bits.h:630
typename array_filter2< Type, S >::type type
Definition: bits.h:622
auto get() noexcept -> auto
Definition: bits.h:627
auto operator=(const Type val) noexcept -> pun_proxy &
Definition: bits.h:551
auto get() &noexcept -> decltype(auto)
Definition: bits.h:701
auto get() &&noexcept -> decltype(auto)
Definition: bits.h:710
typename base_t< I >::type element_t
Definition: bits.h:698
auto get() const &noexcept -> decltype(auto)
Definition: bits.h:706
auto get() const &&noexcept -> decltype(auto)
Definition: bits.h:714
typename kblib::punner< Types... >::template element_t< I > type
Definition: bits.h:725
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
Contains some type traits not in the standard library that are useful in the implementation of kblib.
Definition: bits.cpp:171