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.

158 line
5.1 KiB

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