General Purpose library for Freestanding C++ and POSIX systems
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

203 lines
5.2 KiB

  1. #pragma once
  2. #include <type_traits>
  3. #include "gp/algorithm/move.hpp"
  4. namespace gp {
  5. template<typename F, typename ... Args>
  6. auto bind_front(F&& func, Args&&... arg_parent)
  7. {
  8. return [=](auto&&... argv){
  9. return func(arg_parent..., argv...);
  10. };
  11. }
  12. /* Code extrated from cppreference.com and the libc++ Library project, licensed under MIT license */
  13. namespace detail {
  14. template <class>
  15. constexpr bool is_reference_wrapper_v = false;
  16. template <class U>
  17. constexpr bool is_reference_wrapper_v<std::reference_wrapper<U>> = true;
  18. template <class T, class Type, class T1, class... Args>
  19. constexpr decltype(auto) INVOKE(Type T::* f, T1&& t1, Args&&... args)
  20. {
  21. if constexpr (std::is_member_function_pointer_v<decltype(f)>) {
  22. if constexpr (std::is_base_of_v<T, std::decay_t<T1>>)
  23. return (gp::forward<T1>(t1).*f)(gp::forward<Args>(args)...);
  24. else if constexpr (is_reference_wrapper_v<std::decay_t<T1>>)
  25. return (t1.get().*f)(gp::forward<Args>(args)...);
  26. else
  27. return ((*gp::forward<T1>(t1)).*f)(gp::forward<Args>(args)...);
  28. } else {
  29. static_assert(std::is_member_object_pointer_v<decltype(f)>);
  30. static_assert(sizeof...(args) == 0);
  31. if constexpr (std::is_base_of_v<T, std::decay_t<T1>>)
  32. return gp::forward<T1>(t1).*f;
  33. else if constexpr (is_reference_wrapper_v<std::decay_t<T1>>)
  34. return t1.get().*f;
  35. else
  36. return (*gp::forward<T1>(t1)).*f;
  37. }
  38. }
  39. template <class F, class... Args>
  40. constexpr decltype(auto) INVOKE(F&& f, Args&&... args)
  41. {
  42. return gp::forward<F>(f)(gp::forward<Args>(args)...);
  43. }
  44. } // namespace detail
  45. template< class F, class... Args>
  46. constexpr std::invoke_result_t<F, Args...> invoke(F&& f, Args&&... args)
  47. noexcept(std::is_nothrow_invocable_v<F, Args...>)
  48. {
  49. return detail::INVOKE(gp::forward<F>(f), gp::forward<Args>(args)...);
  50. }
  51. template< class T >
  52. struct remove_cvref {
  53. typedef std::remove_cv_t<std::remove_reference_t<T>> type;
  54. };
  55. template< class T >
  56. using remove_cvref_t = typename remove_cvref<T>::type;
  57. template< class T >
  58. T* addressof(T& arg)
  59. {
  60. return reinterpret_cast<T*>(
  61. &const_cast<char&>(
  62. reinterpret_cast<const volatile char&>(arg)));
  63. }
  64. namespace detail {
  65. template <class T> constexpr T& FUN(T& t) noexcept { return t; }
  66. template <class T> void FUN(T&&) = delete;
  67. }
  68. template <class T>
  69. class reference_wrapper {
  70. public:
  71. // types
  72. typedef T type;
  73. // construct/copy/destroy
  74. template <class U, class = decltype(
  75. detail::FUN<T>(std::declval<U>()),
  76. std::enable_if_t<!std::is_same_v<reference_wrapper, gp::remove_cvref_t<U>>>()
  77. )>
  78. constexpr reference_wrapper(U&& u) noexcept(noexcept(detail::FUN<T>(gp::forward<U>(u))))
  79. : _ptr(gp::addressof(detail::FUN<T>(gp::forward<U>(u)))) {}
  80. reference_wrapper(const reference_wrapper&) noexcept = default;
  81. // assignment
  82. reference_wrapper& operator=(const reference_wrapper& x) noexcept = default;
  83. // access
  84. constexpr operator T& () const noexcept { return *_ptr; }
  85. constexpr T& get() const noexcept { return *_ptr; }
  86. template< class... ArgTypes >
  87. constexpr std::invoke_result_t<T&, ArgTypes...>
  88. operator() ( ArgTypes&&... args ) const {
  89. return gp::invoke(get(), gp::forward<ArgTypes>(args)...);
  90. }
  91. private:
  92. T* _ptr;
  93. };
  94. // deduction guides
  95. template<class T>
  96. reference_wrapper(T&) -> reference_wrapper<T>;
  97. template<typename T>
  98. auto ref(T& vref) {
  99. return reference_wrapper<T>(vref);
  100. }
  101. template <class _DecayFunc>
  102. class __not_fn_imp {
  103. _DecayFunc __fd;
  104. public:
  105. __not_fn_imp() = delete;
  106. template <class ..._Args>
  107. auto operator()(_Args&& ...__args) &
  108. noexcept(noexcept(!gp::invoke(__fd, gp::forward<_Args>(__args)...)))
  109. -> decltype( !gp::invoke(__fd, gp::forward<_Args>(__args)...))
  110. { return !gp::invoke(__fd, gp::forward<_Args>(__args)...); }
  111. template <class ..._Args>
  112. auto operator()(_Args&& ...__args) &&
  113. noexcept(noexcept(!gp::invoke(gp::move(__fd), gp::forward<_Args>(__args)...)))
  114. -> decltype( !gp::invoke(gp::move(__fd), gp::forward<_Args>(__args)...))
  115. { return !gp::invoke(gp::move(__fd), gp::forward<_Args>(__args)...); }
  116. template <class ..._Args>
  117. auto operator()(_Args&& ...__args) const&
  118. noexcept(noexcept(!gp::invoke(__fd, gp::forward<_Args>(__args)...)))
  119. -> decltype( !gp::invoke(__fd, gp::forward<_Args>(__args)...))
  120. { return !gp::invoke(__fd, gp::forward<_Args>(__args)...); }
  121. template <class ..._Args>
  122. auto operator()(_Args&& ...__args) const&&
  123. noexcept(noexcept(!gp::invoke(gp::move(__fd), gp::forward<_Args>(__args)...)))
  124. -> decltype( !gp::invoke(gp::move(__fd), gp::forward<_Args>(__args)...))
  125. { return !gp::invoke(gp::move(__fd), gp::forward<_Args>(__args)...); }
  126. private:
  127. template <class _RawFunc,
  128. class = std::enable_if_t<!std::is_same<std::decay_t<_RawFunc>, __not_fn_imp>::value>>
  129. explicit __not_fn_imp(_RawFunc&& __rf)
  130. : __fd(gp::forward<_RawFunc>(__rf)) {}
  131. template <class _RawFunc>
  132. friend inline __not_fn_imp<std::decay_t<_RawFunc>> not_fn(_RawFunc&&);
  133. };
  134. template <class _RawFunc>
  135. inline __not_fn_imp<std::decay_t<_RawFunc>> not_fn(_RawFunc&& __fn) {
  136. return __not_fn_imp<std::decay_t<_RawFunc>>(gp::forward<_RawFunc>(__fn));
  137. }
  138. }