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