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