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