kblib 0.2.3
General utilities library for modern C++
fakestd.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 KBLIB_FAKESTD_H
33#define KBLIB_FAKESTD_H
34
35#include "tdecl.h"
36
37#include <array>
38#include <limits>
39#include <memory>
40#include <type_traits>
41#include <utility>
42
43#if __has_include("gsl/pointers")
44# include "gsl/pointers"
45#endif
46
47#ifndef KBLIB_FAKESTD
48# define KBLIB_FAKESTD (__cplusplus < 201703L)
49#endif
50
51namespace KBLIB_NS {
52
53#if __has_include("gsl/pointers")
54using gsl::owner;
55#else
56template <class T, class = std::enable_if_t<std::is_pointer<T>::value>>
57using owner = T;
58#endif
59
60template <bool B, typename T = void>
61using enable_if_t = typename std::enable_if<B, T>::type;
62
63template <typename T>
64using decay_t = typename std::decay<T>::type;
65
66template <typename T>
68 typename std::remove_reference<typename std::remove_cv<T>::type>::type;
69
70template <bool v>
71using bool_constant = std::integral_constant<bool, v>;
72
73#if __cpp_lib_constexpr_functional
74using std::invoke;
75#else
76
77# if __cpp_lib_apply
78
79template <typename F, typename... Args>
80constexpr auto invoke(F&& f, Args&&... args) noexcept(noexcept(std::apply(
81 std::forward<F>(f), std::forward_as_tuple(std::forward<Args>(args)...))))
82 -> decltype(auto) {
83 return std::apply(std::forward<F>(f),
84 std::forward_as_tuple(std::forward<Args>(args)...));
85}
86
87# else
88
89namespace detail {
90
91 template <typename F, typename... Args,
92 enable_if_t<not std::is_member_pointer<remove_cvref_t<F>>::value,
93 int> = 0>
94 constexpr auto do_invoke(F&& f, Args&&... args) noexcept(noexcept(
95 std::forward<F>(f)(std::forward<Args>(args)...))) -> decltype(auto) {
96 return std::forward<F>(f)(std::forward<Args>(args)...);
97 }
98
99 template <typename F, typename Object, typename... Args,
101 and std::is_member_function_pointer<F>::value,
102 int> = 0>
103 constexpr auto do_invoke(F f, Object&& obj, Args&&... args) noexcept(
104 noexcept((std::forward<Object>(obj).*f)(std::forward<Args>(args)...)))
105 -> decltype(auto) {
106 return (obj.*f)(std::forward<Args>(args)...);
107 }
108
109 template <typename F, typename Pointer, typename... Args,
111 and std::is_member_function_pointer<F>::value,
112 int> = 0>
113 constexpr auto do_invoke(F f, Pointer ptr, Args&&... args) noexcept(
114 noexcept((ptr->*f)(std::forward<Args>(args)...))) -> decltype(auto) {
115 return (ptr->*f)(std::forward<Args>(args)...);
116 }
117
118 template <typename Member, typename Object,
120 and std::is_member_object_pointer<Member>::value,
121 int> = 0>
122 constexpr auto do_invoke(Member mem, Object&& obj) noexcept
123 -> decltype(auto) {
124 return std::forward<Object>(obj).*mem;
125 }
126
127 template <typename Member, typename Pointer,
129 and std::is_member_object_pointer<Member>::value,
130 int> = 0>
131 constexpr auto do_invoke(Member mem, Pointer ptr) noexcept
132 -> decltype(auto) {
133 return ptr.*mem;
134 }
135} // namespace detail
136
137template <typename F, typename... Args>
138constexpr auto invoke(F&& f, Args&&... args) noexcept(noexcept(
139 detail::do_invoke(std::forward<F>(f), std::forward<Args>(args)...)))
140 -> decltype(auto) {
141 return detail::do_invoke(std::forward<F>(f), std::forward<Args>(args)...);
142}
143
144# endif // __cpp_lib_apply
145#endif // __cpp_lib_constexpr_functional
146
152#if KBLIB_FAKESTD
153namespace fakestd { // C++14 implementation of C++17 void_t, invoke_result,
154 // (partially) is_invocable, and is_nothrow_swappable
155 using std::swap;
156
163 namespace detail {
164
165 template <typename AlwaysVoid, typename, typename...>
166 struct invoke_result {};
167 template <typename F, typename... Args>
168 struct invoke_result<decltype(void(invoke(std::declval<F>(),
169 std::declval<Args>()...))),
170 F, Args...> {
171 using type
172 = decltype(invoke(std::declval<F>(), std::declval<Args>()...));
173 };
174 } // namespace detail
175 template <class F, class... ArgTypes>
176 struct invoke_result : detail::invoke_result<void, F, ArgTypes...> {};
177
178 template <typename F, typename... ArgTypes>
179 using invoke_result_t = typename invoke_result<F, ArgTypes...>::type;
180
181 template <typename... Ts>
182 struct make_void {
183 typedef void type;
184 };
185 template <typename... Ts>
186 using void_t = typename make_void<Ts...>::type;
187
188 namespace detail {
189 // ALL generic swap overloads MUST already have a declaration available at
190 // this point.
191
192 struct nat {
193 nat() = delete;
194 nat(const nat&) = delete;
195 nat& operator=(const nat&) = delete;
196 ~nat() = delete;
197 };
198
199 struct two {
200 char lx[2];
201 };
202
204 template <class Tp>
205 static Tp& test(int);
206 template <class Tp>
207 static two test(...);
208 };
209
210 template <class Tp>
212 : std::integral_constant<
213 bool,
214 not std::is_same<decltype(is_referenceable_impl::test<Tp>(0)),
215 two>::value> {};
216
217 template <class Tp, class Up = Tp,
218 bool NotVoid
219 = not std::is_void<Tp>::value and not std::is_void<Up>::value>
221 template <class LHS, class RHS>
222 static decltype(swap(std::declval<LHS>(), std::declval<RHS>()))
224 template <class, class>
225 static nat test_swap(long);
226
227 // Extra parens are needed for the C++03 definition of decltype.
228 using swap1 = decltype((test_swap<Tp, Up>(0)));
229 using swap2 = decltype((test_swap<Up, Tp>(0)));
230
231 static const bool value = not std::is_same<swap1, nat>::value
232 and not std::is_same<swap2, nat>::value;
233 };
234
235 template <class Tp, class Up>
236 struct swappable_with<Tp, Up, false> : std::false_type {};
237
238 template <class Tp, class Up = Tp,
239 bool Swappable = swappable_with<Tp, Up>::value>
241 static const bool value = noexcept(
242 swap(std::declval<Tp>(),
243 std::declval<Up>()))and noexcept(swap(std::declval<Up>(),
244 std::declval<Tp>()));
245 };
246
247 template <class Tp, class Up>
248 struct nothrow_swappable_with<Tp, Up, false> : std::false_type {};
249
250 } // namespace detail
251
252 template <class Tp>
254 : public std::integral_constant<bool,
255 detail::swappable_with<Tp&>::value> {};
256
257 template <class Tp>
259 : public std::integral_constant<
260 bool, detail::nothrow_swappable_with<Tp&>::value> {};
261
262# if KBLIB_USE_CXX17
263
264 template <class Tp, class Up>
266 : public std::integral_constant<bool,
267 detail::swappable_with<Tp, Up>::value> {
268 };
269
270 template <class Tp>
271 struct is_swappable
272 : public std::conditional<
273 detail::is_referenceable<Tp>::value,
274 is_swappable_with<typename std::add_lvalue_reference<Tp>::type,
275 typename std::add_lvalue_reference<Tp>::type>,
276 std::false_type>::type {};
277
278 template <class Tp, class Up>
280 : public integral_constant<
281 bool, detail::nothrow_swappable_with<Tp, Up>::value> {};
282
283 template <class Tp>
285 : public conditional<
286 detail::is_referenceable<Tp>::value,
287 is_nothrow_swappable_with<typename add_lvalue_reference<Tp>::type,
288 typename add_lvalue_reference<Tp>::type>,
289 false_type>::type {};
290
291 template <class Tp, class Up>
293
294 template <class Tp>
296
297 template <class Tp, class Up>
300
301 template <class Tp>
303
304# endif
305
306 namespace detail {
307 template <typename F>
308 struct not_fn_t {
309 constexpr explicit not_fn_t(F&& f)
310 : fd(std::forward<F>(f)) {}
311 constexpr not_fn_t(const not_fn_t&) = default;
312 constexpr not_fn_t(not_fn_t&&) = default;
313
314 template <class... Args>
315 constexpr auto operator()(Args&&... args) & -> decltype(
316 not std::declval<invoke_result_t<std::decay_t<F>&, Args...>>()) {
317 return not invoke(fd, std::forward<Args>(args)...);
318 }
319
320 template <class... Args>
321 constexpr auto operator()(Args&&... args) const& -> decltype(
322 not std::declval<
323 invoke_result_t<std::decay_t<F> const&, Args...>>()) {
324 return not invoke(std::move(fd), std::forward<Args>(args)...);
325 }
326
327 std::decay_t<F> fd;
328 };
329 } // namespace detail
330
331 template <typename F>
333 return detail::not_fn_t<F>(std::forward<F>(f));
334 }
335
336 struct in_place_t {
337 explicit in_place_t() = default;
338 };
339 static constexpr in_place_t in_place{};
340
341 template <class ForwardIt>
342 constexpr auto max_element(ForwardIt first, ForwardIt last) -> ForwardIt {
343 if (first == last)
344 return last;
345
346 ForwardIt largest = first;
347 ++first;
348 for (; first != last; ++first) {
349 if (*largest < *first) {
350 largest = first;
351 }
352 }
353 return largest;
354 }
355
356 template <class ForwardIt, class Compare>
357 constexpr auto max_element(ForwardIt first, ForwardIt last, Compare comp)
358 -> ForwardIt {
359 if (first == last)
360 return last;
361
362 ForwardIt largest = first;
363 ++first;
364 for (; first != last; ++first) {
365 if (comp(*largest, *first)) {
366 largest = first;
367 }
368 }
369 return largest;
370 }
371
372 template <class C>
373 constexpr auto size(const C& c) -> decltype(c.size()) {
374 return c.size();
375 }
376
377 template <class T, std::size_t N>
378 constexpr auto size(const T (&)[N]) noexcept -> std::size_t {
379 return N;
380 }
381
382 // Adapted from libstdc++ code, licensed under GPL
383
384 namespace detail {
385 // invokable
386 template <class Ret, class Fp, class... Args>
387 struct invokable_r {
388 template <class XFp, class... XArgs>
389 static auto try_call(int)
390 -> decltype(kblib::invoke(std::declval<XFp>(),
391 std::declval<XArgs>()...));
392 template <class XFp, class... XArgs>
393 static auto try_call(...) -> detail::nat;
394
395 using Result = decltype(try_call<Fp, Args...>(0));
396
397 using type = typename std::conditional<
398 not std::is_same<Result, detail::nat>::value,
399 typename std::conditional<std::is_void<Ret>::value, std::true_type,
400 std::is_convertible<Result, Ret>>::type,
401 std::false_type>::type;
402 static const bool value = type::value;
403 };
404 template <class Fp, class... Args>
405 using invokable = invokable_r<void, Fp, Args...>;
406
407 template <bool IsInvokable, bool IsCVVoid, class Ret, class Fp,
408 class... Args>
410 static const bool value = false;
411 };
412
413 template <class Ret, class Fp, class... Args>
414 struct nothrow_invokable_r_imp<true, false, Ret, Fp, Args...> {
416
417 template <class Tp>
418 static void test_noexcept(Tp) noexcept;
419
420 static const bool value = noexcept(ThisT::test_noexcept<Ret>(
421 kblib::invoke(std::declval<Fp>(), std::declval<Args>()...)));
422 };
423
424 template <class Ret, class Fp, class... Args>
425 struct nothrow_invokable_r_imp<true, true, Ret, Fp, Args...> {
426 static const bool value = noexcept(
427 kblib::invoke(std::declval<Fp>(), std::declval<Args>()...));
428 };
429
430 template <class Ret, class Fp, class... Args>
432 = nothrow_invokable_r_imp<invokable_r<Ret, Fp, Args...>::value,
433 std::is_void<Ret>::value, Ret, Fp, Args...>;
434
435 template <class Fp, class... Args>
437 = nothrow_invokable_r_imp<invokable<Fp, Args...>::value, true, void,
438 Fp, Args...>;
439
440 template <class Fp, class... Args>
442 : public std::enable_if<
443 invokable<Fp, Args...>::value,
444 typename invokable_r<void, Fp, Args...>::Result> {};
445 } // namespace detail
446
447 // is_invocable
448
449 template <class Fn, class... Args>
451 : std::integral_constant<bool, detail::invokable<Fn, Args...>::value> {};
452
453 template <class Ret, class Fn, class... Args>
455 : std::integral_constant<bool,
456 detail::invokable_r<Ret, Fn, Args...>::value> {
457 };
458
459 template <class Fn, class... Args>
460 constexpr bool is_invocable_v = is_invocable<Fn, Args...>::value;
461
462 template <class Ret, class Fn, class... Args>
463 constexpr bool is_invocable_r_v = is_invocable_r<Ret, Fn, Args...>::value;
464
465 // is_nothrow_invocable
466
467 template <class Fn, class... Args>
469 : std::integral_constant<bool,
470 detail::nothrow_invokable<Fn, Args...>::value> {
471 };
472
473 template <class Ret, class Fn, class... Args>
475 : std::integral_constant<
476 bool, detail::nothrow_invokable_r<Ret, Fn, Args...>::value> {};
477
478 template <class Fn, class... Args>
480 = is_nothrow_invocable<Fn, Args...>::value;
481
482 template <class Ret, class Fn, class... Args>
484 = is_nothrow_invocable_r<Ret, Fn, Args...>::value;
485
486} // namespace fakestd
487#else
488namespace fakestd = std;
489#endif
490
493
496
499
502
503template <typename... Ts>
504struct meta_type {};
505
506template <typename T>
507struct meta_type<T> {
508 using type = T;
509};
510
511template <typename... Ts>
512using meta_type_t = typename meta_type<Ts...>::type;
513
514template <bool>
515struct void_if {};
516
517template <>
518struct void_if<true> : meta_type<void> {};
519template <bool b>
521
522using fakestd::void_t;
523
524// metafunction_success:
525// SFINAE detector for a ::type member type
526template <typename T, typename = void>
527struct metafunction_success : std::false_type {};
528
529template <typename T>
530struct metafunction_success<T, void_t<typename T::type>> : std::true_type {};
531
532template <typename... T>
533struct is_callable : metafunction_success<fakestd::invoke_result<T...>> {};
534
535template <typename T>
537 = std::integral_constant<decltype(T::value), T::value>;
538
543template <bool V, typename T>
545
546template <typename T>
547struct return_assert<true, T> : meta_type<T> {};
548
549template <bool V, typename T>
551
552namespace detail {
553
554 template <typename F, typename Arg, typename = void>
555 struct apply_impl {
556 template <std::size_t... Is>
557 constexpr static auto do_apply(F&& f, Arg&& arg) noexcept(
558 noexcept(kblib::invoke(std::forward<F>(f),
559 std::get<Is>(std::forward<Arg>(arg))...)))
560 -> decltype(auto) {
561 return kblib::invoke(std::forward<F>(f),
562 std::get<Is>(std::forward<Arg>(arg))...);
563 }
564 };
565
566} // namespace detail
567
568template <typename F, typename Arg>
569constexpr auto apply(F&& f, Arg&& arg) noexcept(
571 std::forward<F>(f), std::forward<Arg>(arg),
572 std::index_sequence<std::tuple_size<Arg>::value>{})))
573 -> decltype(auto) {
574 return detail::apply_impl<F, Arg>::do_apply(
575 std::forward<F>(f), std::forward<Arg>(arg),
576 std::index_sequence<std::tuple_size<Arg>::value>{});
577}
578
579template <typename T>
580KBLIB_NODISCARD auto to_unique(owner<T*> p) -> std::unique_ptr<T> {
581 return std::unique_ptr<T>(p);
582}
583template <typename T, typename D>
584KBLIB_NODISCARD auto to_unique(owner<T*> p, D&& d) -> std::unique_ptr<T, D> {
585 return std::unique_ptr<T, D>(p, d);
586}
587
591template <typename I>
592KBLIB_NODISCARD constexpr auto to_unsigned(I x) -> std::make_unsigned_t<I> {
593 return static_cast<std::make_unsigned_t<I>>(x);
594}
598template <typename I>
599KBLIB_NODISCARD constexpr auto to_signed(I x) -> std::make_signed_t<I> {
600 return static_cast<std::make_signed_t<I>>(x);
601}
602
607template <typename A, typename F>
608KBLIB_NODISCARD constexpr auto signed_cast(F x)
609 -> enable_if_t<std::is_integral<A>::value and std::is_integral<F>::value
610 and std::is_signed<A>::value,
611 std::make_signed_t<F>> {
612 return to_signed(x);
613}
614
619template <typename A, typename F>
620KBLIB_NODISCARD constexpr auto signed_cast(F x)
621 -> enable_if_t<std::is_integral<A>::value and std::is_integral<F>::value
622 and std::is_unsigned<A>::value,
623 std::make_unsigned_t<F>> {
624 return to_unsigned(x);
625}
626
627template <typename T>
629 private:
630 using yes = char (&)[1];
631 using no = char (&)[2];
632
633 template <typename C>
634 static auto check(decltype(&C::swap)) -> yes;
635 template <typename>
636 static auto check(...) -> no;
637
638 public:
639 constexpr static bool value = sizeof(check<T>(nullptr)) == sizeof(yes);
640};
641
642template <typename T, typename = void>
643struct is_tuple_like : std::false_type {};
644
645template <typename T>
646struct is_tuple_like<T, void_t<typename std::tuple_element<0, T>::type>>
647 : std::true_type {};
648
649namespace detail {
650
651 template <typename... Ts>
652 constexpr auto ignore(Ts&&... /*unused*/) noexcept -> void {}
653
654 template <typename T, std::size_t... Is>
655 constexpr auto
656 swap_tuple_impl(T& a, T& b, std::index_sequence<Is...> /*unused*/) noexcept(
657 noexcept(ignore(((void)swap(std::get<Is>(a), std::get<Is>(b)), 0)...)))
658 -> void {
659 ignore(((void)swap(std::get<Is>(a), std::get<Is>(b)), 0)...);
660 }
661
662} // namespace detail
663
664KBLIB_UNUSED struct {
670 template <typename T, enable_if_t<not has_member_swap<T>::value
671 and not is_tuple_like<T>::value,
672 int> = 0>
673 KBLIB_UNUSED constexpr auto operator()(T& a, T& b) const
674 noexcept(std::is_nothrow_move_constructible<T>::value and
675 std::is_nothrow_move_assignable<T>::value) -> void {
676 auto tmp = std::move(a);
677 a = std::move(b);
678 b = std::move(tmp);
679 return;
680 }
681
687 template <typename T, enable_if_t<has_member_swap<T>::value, int> = 0>
688 KBLIB_UNUSED constexpr auto operator()(T& a, T& b) const
689 noexcept(noexcept(a.swap(b))) -> void {
690 a.swap(b);
691 return;
692 }
693
699 template <typename T, std::size_t N>
700 KBLIB_UNUSED constexpr auto operator()(T (&a)[N], T (&b)[N]) const
701 noexcept(std::is_nothrow_move_constructible<T>::value and
702 std::is_nothrow_move_assignable<T>::value) -> void {
703 for (std::size_t i = 0; i < N; ++i) {
704 swap(a[i], b[i]);
705 }
706 }
707
713 template <typename T, enable_if_t<is_tuple_like<T>::value
714 and not has_member_swap<T>::value,
715 std::size_t>
716 N
717 = std::tuple_size<T>::value>
718 KBLIB_UNUSED constexpr auto operator()(T& a, T& b) const noexcept(noexcept(
719 detail::swap_tuple_impl(a, b, std::make_index_sequence<N>{}))) -> void {
720 detail::swap_tuple_impl(a, b, std::make_index_sequence<N>{});
721 }
723
724template <typename T, typename U = T>
725KBLIB_NODISCARD constexpr auto exchange(T& obj, U&& new_value) -> T {
726 T old_value = std::move(obj);
727 obj = std::forward<U>(new_value);
728 return old_value;
729}
730
731#if KBLIB_USE_CXX17
732
733namespace detail {
734
735 template <typename T>
736 constexpr std::intmax_t max_val = std::numeric_limits<T>::max();
737
738 KBLIB_NODISCARD constexpr auto msb(std::uintmax_t x) -> std::uintmax_t {
739 x |= (x >> 1u);
740 x |= (x >> 2u);
741 x |= (x >> 4u);
742 x |= (x >> 8u);
743 x |= (x >> 16u);
744 x |= (x >> 32u);
745 return (x & ~(x >> 1u));
746 }
747
748 template <typename Num>
749 KBLIB_NODISCARD constexpr auto msb_possible() -> Num {
750 return static_cast<Num>(typename std::make_unsigned<Num>::type{1}
751 << (std::numeric_limits<Num>::digits - 1u));
752 }
753
754 template <class... Args>
755 struct type_list {
756 template <std::size_t N>
757 using type = typename std::tuple_element<N, std::tuple<Args...>>::type;
758 };
759
760 template <auto K, typename V>
761 struct type_map_el {
762 constexpr static auto key = K;
763 using value = V;
764 };
765
766 template <typename Key, typename Comp, typename... Vals>
767 struct type_map {
768 using types = type_list<Vals...>;
769 template <std::size_t I>
770 using element = typename types::template type<I>;
771
772 template <Key key, std::size_t I = 0>
773 KBLIB_NODISCARD constexpr static auto get() noexcept -> auto {
774 static_assert(I < sizeof...(Vals), "key not found");
775 if constexpr (Comp{}(key, element<I>::key)) {
777 } else {
778 return get<key, I + 1>();
779 }
780 }
781
782 template <Key key, typename Default = void, std::size_t I = 0>
783 KBLIB_NODISCARD constexpr static auto get_default() noexcept -> auto {
784 if constexpr (I == sizeof...(Vals)) {
785 return Default();
786 } else if constexpr (Comp{}(key, element<I>::key)) {
788 } else {
789 return get<key, I + 1>();
790 }
791 }
792 };
793
794 template <typename N>
796 = type_map_el<static_cast<std::intmax_t>(msb_possible<N>()), N>;
797
798 template <typename T>
800 static_assert(max_val<T> < max_val<std::intmax_t>,
801 "Cannot safely promote intmax_t.");
803 template <typename U>
804 constexpr auto operator()(U, U) noexcept -> bool {
805 return true;
806 }
807 };
808
810 std::intmax_t, std::less<>, make_smap_el<std::int_least8_t>,
813
814 using type = typename decltype(
815 ints_map::template get_default<max_val<T> + 1>())::type;
816 };
817
818 template <typename N, bool = std::is_signed<N>::value>
820
821 template <typename N>
822 struct filter_signed<N, true> {
823 using type = N;
824 };
825
826 template <typename N>
828
829 template <typename N, bool = std::is_unsigned<N>::value>
831
832 template <typename N>
833 struct filter_unsigned<N, true> {
834 using type = N;
835 };
836
837 template <typename N>
839
840} // namespace detail
841
842template <typename N, typename = void>
844
845template <typename N>
846struct safe_signed<N, std::enable_if_t<std::is_integral<N>::value, void>> {
847 using type = std::conditional_t<
848 std::is_signed<N>::value, N,
850};
851
852template <typename N>
854
855template <typename N>
856KBLIB_NODISCARD constexpr auto signed_promote(N x) noexcept
858 return static_cast<safe_signed_t<N>>(x);
859}
860
861#endif
862
863template <typename C, typename T,
864 bool = std::is_const<typename std::remove_reference<C>::type>::value>
865struct copy_const : meta_type<T> {};
866
867template <typename C, typename T>
868struct copy_const<C, T, true> : meta_type<const T> {};
869
870template <typename C, typename T>
871struct copy_const<C, T&, true> : meta_type<const T&> {};
872
873template <typename C, typename T>
874struct copy_const<C, T&&, true> : meta_type<const T&&> {};
875
876template <typename C, typename V>
878
879template <typename T, typename = void>
880struct value_detected : std::false_type {};
881
882template <typename T>
883struct value_detected<T, void_t<typename T::value_type>> : std::true_type {
884 using type = typename T::value_type;
885};
886
887template <typename T>
889template <typename T>
891
892template <typename T, typename = void>
893struct key_detected : std::false_type {};
894
895template <typename T>
896struct key_detected<T, void_t<typename T::key_type>> : std::true_type {
897 using type = typename T::key_type;
898};
899
900template <typename T>
902template <typename T>
904
905template <typename T, typename = void>
906struct mapped_detected : std::false_type {};
907
908template <typename T>
909struct mapped_detected<T, void_t<typename T::mapped_type>> : std::true_type {
910 using type = typename T::mapped_type;
911};
912
913template <typename T>
915template <typename T>
917
918template <typename T, typename = void>
919struct hash_detected : std::false_type {};
920
921template <typename T>
922struct hash_detected<T, void_t<typename T::hasher>> : std::true_type {
923 using type = typename T::hasher;
924};
925
926template <typename T>
928template <typename T>
930
931template <typename Container, bool = key_detected_v<Container>,
932 typename T = typename Container::value_type>
934
935template <typename Container>
936struct value_type_linear<Container, false, typename Container::value_type>
937 : meta_type<typename Container::value_type> {};
938
939template <typename Container>
941
942template <typename Container>
943constexpr static bool is_linear_container_v
944 = value_detected_v<Container> and not key_detected_v<Container>;
945
946template <typename Container>
947struct is_linear_container : bool_constant<is_linear_container_v<Container>> {};
948
949template <typename Container, bool = key_detected_v<Container>,
950 bool = mapped_detected_v<Container>>
952
953template <typename Container>
954struct key_type_setlike<Container, true, false>
955 : meta_type<typename Container::key_type> {};
956
957template <typename Container>
959
960template <typename Container>
961constexpr static bool is_setlike_v
963 Container> and value_detected_v<Container> and not mapped_detected_v<Container> and std::is_same<key_detected_t<Container>, value_detected_t<Container>>::value);
964
965template <class InputIt1, class InputIt2>
966KBLIB_NODISCARD constexpr auto equal(InputIt1 first1, InputIt1 last1,
967 InputIt2 first2) -> bool {
968 for (; first1 != last1; ++first1, ++first2) {
969 if (not (*first1 == *first2)) {
970 return false;
971 }
972 }
973 return true;
974}
975
976template <typename InputIt1, typename InputIt2, typename BinaryPredicate,
977 typename kblib::enable_if_t<
978 not std::is_same<InputIt2, BinaryPredicate>::value, int> = 0>
979KBLIB_NODISCARD constexpr auto equal(InputIt1 first1, InputIt1 last1,
980 InputIt2 first2, BinaryPredicate p)
981 -> bool {
982 for (; first1 != last1; ++first1, ++first2) {
983 if (not p(*first1, *first2)) {
984 return false;
985 }
986 }
987 return true;
988}
989template <class RandomIt1, class RandomIt2,
990 typename kblib::enable_if_t<
991 std::is_base_of<std::random_access_iterator_tag,
992 typename std::iterator_traits<
993 RandomIt1>::iterator_category>::value
994 and std::is_base_of<std::random_access_iterator_tag,
995 typename std::iterator_traits<
996 RandomIt2>::iterator_category>::value,
997 int> = 0>
998KBLIB_NODISCARD constexpr auto equal(RandomIt1 first1, RandomIt1 last1,
999 RandomIt2 first2, RandomIt2 last2)
1000 -> bool {
1001 if (std::distance(first1, last1) == std::distance(first2, last2)) {
1002 return false;
1003 }
1004 for (; first1 != last1; ++first1, ++first2) {
1005 if (not (*first1 == *first2)) {
1006 return false;
1007 }
1008 }
1009 return true;
1010}
1011
1012template <class RandomIt1, class RandomIt2, typename BinaryPredicate,
1013 typename kblib::enable_if_t<
1014 std::is_base_of<std::random_access_iterator_tag,
1015 typename std::iterator_traits<
1016 RandomIt1>::iterator_category>::value
1017 and std::is_base_of<std::random_access_iterator_tag,
1018 typename std::iterator_traits<
1019 RandomIt2>::iterator_category>::value,
1020 int> = 0>
1021KBLIB_NODISCARD constexpr auto equal(RandomIt1 first1, RandomIt1 last1,
1022 RandomIt2 first2, RandomIt2 last2,
1023 BinaryPredicate p) -> bool {
1024 if (std::distance(first1, last1) == std::distance(first2, last2)) {
1025 return false;
1026 }
1027 for (; first1 != last1; ++first1, ++first2) {
1028 if (not p(*first1, *first2)) {
1029 return false;
1030 }
1031 }
1032 return true;
1033}
1034template <
1035 class InputIt1, class InputIt2,
1036 typename kblib::enable_if_t<
1037 not std::is_base_of<
1038 std::random_access_iterator_tag,
1039 typename std::iterator_traits<InputIt1>::iterator_category>::value
1040 or not std::is_base_of<std::random_access_iterator_tag,
1041 typename std::iterator_traits<
1042 InputIt2>::iterator_category>::value,
1043 int> = 0>
1044KBLIB_NODISCARD constexpr auto equal(InputIt1 first1, InputIt1 last1,
1045 InputIt2 first2, InputIt2 last2) -> bool {
1046 for (; first1 != last1 and first2 != last2; ++first1, ++first2) {
1047 if (not (*first1 == *first2)) {
1048 return false;
1049 }
1050 }
1051 return (first1 == last1 and first2 == last2);
1052}
1053
1054template <
1055 typename InputIt1, typename InputIt2, typename BinaryPredicate,
1056 typename kblib::enable_if_t<
1057 not std::is_base_of<
1058 std::random_access_iterator_tag,
1059 typename std::iterator_traits<InputIt1>::iterator_category>::value
1060 or not std::is_base_of<std::random_access_iterator_tag,
1061 typename std::iterator_traits<
1062 InputIt2>::iterator_category>::value,
1063 int> = 0>
1064KBLIB_NODISCARD constexpr auto equal(InputIt1 first1, InputIt1 last1,
1065 InputIt2 first2, InputIt2 last2,
1066 BinaryPredicate p) -> bool {
1067 for (; first1 != last1 and first2 != last2; ++first1, ++first2) {
1068 if (not p(*first1, *first2)) {
1069 return false;
1070 }
1071 }
1072 return (first1 == last1 and first2 == last2);
1073}
1074
1075template <typename C>
1076KBLIB_NODISCARD constexpr auto size(const C& c) -> decltype(c.size()) {
1077 return c.size();
1078}
1079
1080template <typename T, std::size_t N>
1081KBLIB_NODISCARD constexpr auto size(const T (&)[N]) noexcept -> std::size_t {
1082 return N;
1083}
1084
1085template <class InputIt1, class InputIt2>
1086KBLIB_NODISCARD constexpr auto lexicographical_compare(InputIt1 first1,
1087 InputIt1 last1,
1088 InputIt2 first2,
1089 InputIt2 last2) -> bool {
1090 for (; (first1 != last1) and (first2 != last2); ++first1, (void)++first2) {
1091 if (*first1 < *first2)
1092 return true;
1093 if (*first2 < *first1)
1094 return false;
1095 }
1096 return (first1 == last1) and (first2 != last2);
1097}
1098
1099namespace detail {
1100 template <typename D, typename T, typename = void>
1101 struct pointer {
1102 using type = T*;
1103 };
1104
1105 template <typename D, typename T>
1106 struct pointer<D, T, void_t<typename D::pointer>> {
1107 using type = typename D::pointer;
1108 };
1109
1110} // namespace detail
1111
1112constexpr struct in_place_agg_t {
1114
1115template <typename T>
1117 public:
1118 using element_type = T;
1119 using pointer = T*;
1120 using const_pointer = const T*;
1121 using reference = T&;
1122 using const_reference = const T&;
1123
1124 constexpr heap_value() noexcept
1125 : p{nullptr} {}
1126 constexpr heap_value(std::nullptr_t) noexcept
1127 : p{nullptr} {}
1128
1129 template <typename... Args,
1130 enable_if_t<std::is_constructible<T, Args...>::value> = 0>
1132 : p{new T(args...)} {}
1133 template <typename... Args>
1135 : p{new T{args...}} {}
1136
1138 : p{(u.p ? (new T(*u.p)) : nullptr)} {}
1140 : p{std::exchange(u.p, nullptr)} {}
1141
1142 auto operator=(const heap_value& u) & -> heap_value& {
1143 if (this == &u) {
1144 return *this;
1145 } else if (not u) {
1146 p.reset();
1147 } else if (p) {
1148 *p = *u;
1149 } else {
1150 p.reset(new T(*u.p));
1151 }
1152 return *this;
1153 }
1154
1155 auto operator=(heap_value&& u) & noexcept -> heap_value& {
1156 if (this == &u) {
1157 return *this;
1158 }
1159 p = std::exchange(u.p, nullptr);
1160 return *this;
1161 }
1162
1163 auto operator=(const T& val) & -> heap_value& {
1164 if (this == &val) {
1165 return *this;
1166 }
1167 p.reset(new T(val));
1168 }
1169 auto operator=(T&& val) & -> heap_value& {
1170 if (this == &val) {
1171 return *this;
1172 }
1173 p.reset(new T(std::move(val)));
1174 }
1175
1176 auto assign() & -> void { p.reset(new T()); }
1177 auto assign(const T& val) & -> void { p.reset(new T(val)); }
1178 auto assign(T&& val) & -> void { p.reset(new T(std::move(val))); }
1179 template <typename... Args,
1180 enable_if_t<std::is_constructible<T, Args...>::value> = 0>
1181 auto assign(fakestd::in_place_t, Args&&... args) -> void {
1182 p.reset(new T(std::forward<Args>(args)...));
1183 }
1184 template <typename... Args>
1185 auto assign(in_place_agg_t, Args&&... args) -> void {
1186 p.reset(new T{std::forward<Args>(args)...});
1187 }
1188
1189 auto reset() noexcept -> void {
1190 p.reset();
1191 return;
1192 }
1193
1194 KBLIB_NODISCARD explicit operator bool() const& noexcept {
1195 return p != nullptr;
1196 }
1197
1198 constexpr auto swap(heap_value& other) noexcept -> void {
1199 kblib::swap(p, other.p);
1200 }
1201
1202 KBLIB_NODISCARD auto get() & noexcept -> pointer { return p.get(); }
1203 KBLIB_NODISCARD auto get() const& noexcept -> const_pointer {
1204 return p.get();
1205 }
1206
1207 KBLIB_NODISCARD auto value() & noexcept -> reference { return *p; }
1208 KBLIB_NODISCARD auto value() const& noexcept -> const_reference {
1209 return *p;
1210 }
1211 KBLIB_NODISCARD auto value() && noexcept -> T&& { return *p; }
1212 KBLIB_NODISCARD auto value() const&& noexcept -> const T&& { return *p; }
1213
1214 KBLIB_NODISCARD auto operator*() & noexcept -> reference { return *p; }
1215 KBLIB_NODISCARD auto operator*() const& noexcept -> const_reference {
1216 return *p;
1217 }
1218 KBLIB_NODISCARD auto operator*() && noexcept -> T&& { return *p; }
1219 KBLIB_NODISCARD auto operator*() const&& noexcept -> const T&& { return *p; }
1220
1221 KBLIB_NODISCARD auto operator->() & noexcept -> pointer { return p.get(); }
1222 KBLIB_NODISCARD auto operator->() const& noexcept -> const_pointer {
1223 return p.get();
1224 }
1225
1226 ~heap_value() = default;
1227
1228 private:
1229 std::unique_ptr<element_type> p;
1230};
1231
1232template <typename T, typename D>
1233class heap_value2 : private std::unique_ptr<T, D> {
1234 using Base = std::unique_ptr<T, D>;
1235
1236 public:
1237 using typename Base::deleter_type;
1238 using typename Base::element_type;
1239 using typename Base::pointer;
1240 using reference = decltype(*std::declval<pointer>());
1241 using const_reference = const element_type&;
1242
1243 using Base::Base;
1244 using Base::operator=;
1247
1248 using Base::release;
1249 using Base::reset;
1250 using Base::swap;
1251
1252 using Base::get;
1253 using Base::get_deleter;
1254 using Base::operator bool;
1255
1256 using Base::operator*;
1257 using Base::operator->;
1258
1259 KBLIB_NODISCARD auto value() & noexcept -> reference { return **this; }
1260 KBLIB_NODISCARD auto value() const& noexcept -> const_reference {
1261 return **this;
1262 }
1263 KBLIB_NODISCARD auto value() && noexcept -> element_type&& { return **this; }
1264 KBLIB_NODISCARD auto value() const&& noexcept -> const element_type&& {
1265 return **this;
1266 }
1267
1268 ~heap_value2() = default;
1269};
1270
1271template <typename T, typename D>
1272class heap_value2<T[], D> : private std::unique_ptr<T[], D> {
1273 using Base = std::unique_ptr<T[], D>;
1274
1275 public:
1276 using typename Base::deleter_type;
1277 using typename Base::element_type;
1278 using typename Base::pointer;
1279 using reference = element_type&;
1280 using const_reference = const element_type&;
1281
1282 using Base::Base;
1283 using Base::operator=;
1286
1287 using Base::release;
1288 using Base::reset;
1289 using Base::swap;
1290
1291 using Base::get;
1292 using Base::get_deleter;
1293 using Base::operator bool;
1294
1295 using Base::operator[];
1296
1297 KBLIB_NODISCARD auto value() & noexcept -> reference { return **this; }
1298 KBLIB_NODISCARD auto value() const& noexcept -> const_reference {
1299 return **this;
1300 }
1301 KBLIB_NODISCARD auto value() && noexcept -> element_type&& { return **this; }
1302 KBLIB_NODISCARD auto value() const&& noexcept -> const element_type&& {
1303 return **this;
1304 }
1305
1306 ~heap_value2() = default;
1307};
1308
1309} // namespace KBLIB_NS
1310
1311#endif // KBLIB_FAKESTD_H
auto value() const &noexcept -> const_reference
Definition: fakestd.h:1298
auto value() &&noexcept -> element_type &&
Definition: fakestd.h:1301
auto value() &noexcept -> reference
Definition: fakestd.h:1297
heap_value2 & operator=(const heap_value2 &other)
auto value() const &&noexcept -> const element_type &&
Definition: fakestd.h:1302
heap_value2(const heap_value2 &other)
const element_type & const_reference
Definition: fakestd.h:1280
element_type & reference
Definition: fakestd.h:1279
auto value() &&noexcept -> element_type &&
Definition: fakestd.h:1263
heap_value2 & operator=(const heap_value2 &other)
heap_value2(const heap_value2 &other)
auto value() &noexcept -> reference
Definition: fakestd.h:1259
auto value() const &noexcept -> const_reference
Definition: fakestd.h:1260
auto value() const &&noexcept -> const element_type &&
Definition: fakestd.h:1264
~heap_value2()=default
decltype(*std::declval< pointer >()) reference
Definition: fakestd.h:1240
const element_type & const_reference
Definition: fakestd.h:1241
const T * const_pointer
Definition: fakestd.h:1120
heap_value(heap_value &&u) noexcept
Definition: fakestd.h:1139
auto value() const &noexcept -> const_reference
Definition: fakestd.h:1208
auto assign(in_place_agg_t, Args &&... args) -> void
Definition: fakestd.h:1185
auto reset() noexcept -> void
Definition: fakestd.h:1189
auto operator=(const T &val) &-> heap_value &
Definition: fakestd.h:1163
auto get() const &noexcept -> const_pointer
Definition: fakestd.h:1203
constexpr heap_value() noexcept
Definition: fakestd.h:1124
auto assign(fakestd::in_place_t, Args &&... args) -> void
Definition: fakestd.h:1181
auto value() &noexcept -> reference
Definition: fakestd.h:1207
auto assign() &-> void
Definition: fakestd.h:1176
auto operator=(T &&val) &-> heap_value &
Definition: fakestd.h:1169
auto assign(T &&val) &-> void
Definition: fakestd.h:1178
constexpr auto swap(heap_value &other) noexcept -> void
Definition: fakestd.h:1198
auto operator=(heap_value &&u) &noexcept -> heap_value &
Definition: fakestd.h:1155
auto value() &&noexcept -> T &&
Definition: fakestd.h:1211
auto operator*() &noexcept -> reference
Definition: fakestd.h:1214
auto operator*() const &noexcept -> const_reference
Definition: fakestd.h:1215
auto operator*() const &&noexcept -> const T &&
Definition: fakestd.h:1219
constexpr heap_value(std::nullptr_t) noexcept
Definition: fakestd.h:1126
auto operator->() const &noexcept -> const_pointer
Definition: fakestd.h:1222
auto assign(const T &val) &-> void
Definition: fakestd.h:1177
auto operator->() &noexcept -> pointer
Definition: fakestd.h:1221
auto value() const &&noexcept -> const T &&
Definition: fakestd.h:1212
const T & const_reference
Definition: fakestd.h:1122
heap_value(in_place_agg_t, Args &&... args)
Definition: fakestd.h:1134
heap_value(const heap_value &u)
Definition: fakestd.h:1137
~heap_value()=default
auto get() &noexcept -> pointer
Definition: fakestd.h:1202
auto operator*() &&noexcept -> T &&
Definition: fakestd.h:1218
heap_value(fakestd::in_place_t, Args &&... args)
Definition: fakestd.h:1131
auto operator=(const heap_value &u) &-> heap_value &
Definition: fakestd.h:1142
typename filter_unsigned< N >::type filter_unsigned_t
Definition: fakestd.h:838
constexpr auto ignore(Ts &&...) noexcept -> void
Definition: fakestd.h:652
constexpr auto msb_possible() -> Num
Definition: fakestd.h:749
typename filter_signed< N >::type filter_signed_t
Definition: fakestd.h:827
constexpr auto do_invoke(Member mem, Pointer ptr) noexcept -> decltype(auto)
Definition: fakestd.h:131
constexpr std::intmax_t max_val
Definition: fakestd.h:736
constexpr auto swap_tuple_impl(T &a, T &b, std::index_sequence< Is... >) noexcept(noexcept(ignore(((void) swap(std::get< Is >(a), std::get< Is >(b)), 0)...))) -> void
Definition: fakestd.h:656
constexpr auto msb(std::uintmax_t x) -> std::uintmax_t
Definition: fakestd.h:738
constexpr bool is_swappable_v
Definition: fakestd.h:295
auto not_fn(F &&f) -> detail::not_fn_t< F >
Definition: fakestd.h:332
constexpr bool is_nothrow_swappable_with_v
Definition: fakestd.h:299
typename invoke_result< F, ArgTypes... >::type invoke_result_t
Definition: fakestd.h:179
typename make_void< Ts... >::type void_t
Definition: fakestd.h:186
constexpr bool is_invocable_v
Definition: fakestd.h:460
constexpr bool is_swappable_with_v
Definition: fakestd.h:292
constexpr bool is_nothrow_swappable_v
Definition: fakestd.h:302
constexpr bool is_nothrow_invocable_v
Definition: fakestd.h:480
constexpr auto max_element(ForwardIt first, ForwardIt last, Compare comp) -> ForwardIt
Definition: fakestd.h:357
constexpr bool is_invocable_r_v
Definition: fakestd.h:463
constexpr bool is_nothrow_invocable_r_v
Definition: fakestd.h:484
constexpr struct kblib::nums::max_t max
typename key_type_setlike< Container >::type key_type_setlike_t
Definition: fakestd.h:958
constexpr auto size(const T(&)[N]) noexcept -> std::size_t
Definition: fakestd.h:1081
constexpr auto exchange(T &obj, U &&new_value) -> T
Definition: fakestd.h:725
constexpr bool mapped_detected_v
Definition: fakestd.h:914
constexpr auto to_signed(I x) -> std::make_signed_t< I >
Cast integral argument to corresponding signed type.
Definition: fakestd.h:599
constexpr auto a(const std::initializer_list< T > &a) -> auto
Index an array literal without naming its type.
Definition: simple.h:255
typename std::enable_if< B, T >::type enable_if_t
Definition: fakestd.h:61
constexpr auto apply(F &&f, Arg &&arg) noexcept(noexcept(detail::apply_impl< F, Arg >::do_apply(std::forward< F >(f), std::forward< Arg >(arg), std::index_sequence< std::tuple_size< Arg >::value >{}))) -> decltype(auto)
Definition: fakestd.h:569
struct kblib::@0 swap
std::integral_constant< decltype(T::value), T::value > metafunction_value_t
Definition: fakestd.h:537
T owner
Definition: fakestd.h:57
typename hash_detected< T >::type hash_detected_t
Definition: fakestd.h:929
constexpr bool value_detected_v
Definition: fakestd.h:888
auto get(punner< Types... > &p) noexcept -> decltype(auto)
Definition: bits.h:737
constexpr auto invoke(F &&f, Args &&... args) noexcept(noexcept(detail::do_invoke(std::forward< F >(f), std::forward< Args >(args)...))) -> decltype(auto)
Definition: fakestd.h:138
typename std::decay< T >::type decay_t
Definition: fakestd.h:64
typename value_detected< T >::type value_detected_t
Definition: fakestd.h:890
std::integral_constant< bool, v > bool_constant
Definition: fakestd.h:71
constexpr bool key_detected_v
Definition: fakestd.h:901
typename void_if< b >::type void_if_t
Definition: fakestd.h:520
typename value_type_linear< Container >::type value_type_linear_t
Definition: fakestd.h:940
typename key_detected< T >::type key_detected_t
Definition: fakestd.h:903
constexpr auto signed_cast(F x) -> enable_if_t< std::is_integral< A >::value and std::is_integral< F >::value and std::is_signed< A >::value, std::make_signed_t< F > >
Cast argument to equivalently-sized type with the same signednessas the template parameter.
Definition: fakestd.h:608
typename return_assert< V, T >::type return_assert_t
Definition: fakestd.h:550
typename safe_signed< N >::type safe_signed_t
Definition: fakestd.h:853
typename std::remove_reference< typename std::remove_cv< T >::type >::type remove_cvref_t
Definition: fakestd.h:68
constexpr bool hash_detected_v
Definition: fakestd.h:927
constexpr auto equal(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, BinaryPredicate p) -> bool
Definition: fakestd.h:1064
auto to_unique(owner< T * > p, D &&d) -> std::unique_ptr< T, D >
Definition: fakestd.h:584
constexpr auto signed_promote(N x) noexcept -> safe_signed_t< N >
Definition: fakestd.h:856
typename mapped_detected< T >::type mapped_detected_t
Definition: fakestd.h:916
constexpr auto lexicographical_compare(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2) -> bool
Definition: fakestd.h:1086
constexpr struct kblib::in_place_agg_t in_place_agg
typename copy_const< C, V >::type copy_const_t
Definition: fakestd.h:877
typename meta_type< Ts... >::type meta_type_t
Definition: fakestd.h:512
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
static constexpr auto do_apply(F &&f, Arg &&arg) noexcept(noexcept(kblib::invoke(std::forward< F >(f), std::get< Is >(std::forward< Arg >(arg))...))) -> decltype(auto)
Definition: fakestd.h:557
constexpr auto operator()(U, U) noexcept -> bool
Definition: fakestd.h:804
typename decltype(ints_map::template get_default< max_val< T >+1 >())::type type
Definition: fakestd.h:815
typename std::tuple_element< N, std::tuple< Args... > >::type type
Definition: fakestd.h:757
static constexpr auto get_default() noexcept -> auto
Definition: fakestd.h:783
static constexpr auto get() noexcept -> auto
Definition: fakestd.h:773
typename types::template type< I > element
Definition: fakestd.h:770
typename std::conditional< not std::is_same< Result, detail::nat >::value, typename std::conditional< std::is_void< Ret >::value, std::true_type, std::is_convertible< Result, Ret > >::type, std::false_type >::type type
Definition: fakestd.h:401
static auto try_call(int) -> decltype(kblib::invoke(std::declval< XFp >(), std::declval< XArgs >()...))
static auto try_call(...) -> detail::nat
decltype(try_call< Fp, Args... >(0)) Result
Definition: fakestd.h:395
nat(const nat &)=delete
nat & operator=(const nat &)=delete
constexpr auto operator()(Args &&... args) const &-> decltype(not std::declval< invoke_result_t< std::decay_t< F > const &, Args... > >())
Definition: fakestd.h:321
constexpr not_fn_t(F &&f)
Definition: fakestd.h:309
constexpr not_fn_t(not_fn_t &&)=default
constexpr auto operator()(Args &&... args) &-> decltype(not std::declval< invoke_result_t< std::decay_t< F > &, Args... > >())
Definition: fakestd.h:315
constexpr not_fn_t(const not_fn_t &)=default
decltype((test_swap< Up, Tp >(0))) swap2
Definition: fakestd.h:229
static decltype(swap(std::declval< LHS >(), std::declval< RHS >())) test_swap(int)
decltype((test_swap< Tp, Up >(0))) swap1
Definition: fakestd.h:228
Essentially just like std::enable_if, but with a different name that makes it clearer what it does in...
Definition: fakestd.h:544
std::conditional_t< std::is_signed< N >::value, N, typename detail::next_larger_signed< std::make_signed_t< N > >::type > type
Definition: fakestd.h:849
Provides macros and basic templates used by the rest of kblib.
#define KBLIB_CONSTANT
Definition: tdecl.h:137
#define KBLIB_NS
Definition: tdecl.h:113
#define KBLIB_UNUSED
This internal macro is used to provide a fallback for [[maybe_unused]] in C++14.
Definition: tdecl.h:130
#define KBLIB_NODISCARD
This internal macro is used to provide a fallback for [[nodiscard]] in C++14.
Definition: tdecl.h:129