mofunc_impl.h 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. // Implementation of std::move_only_function -*- C++ -*-
  2. // Copyright The GNU Toolchain Authors.
  3. //
  4. // This file is part of the GNU ISO C++ Library. This library is free
  5. // software; you can redistribute it and/or modify it under the
  6. // terms of the GNU General Public License as published by the
  7. // Free Software Foundation; either version 3, or (at your option)
  8. // any later version.
  9. // This library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. // Under Section 7 of GPL version 3, you are granted additional
  14. // permissions described in the GCC Runtime Library Exception, version
  15. // 3.1, as published by the Free Software Foundation.
  16. // You should have received a copy of the GNU General Public License and
  17. // a copy of the GCC Runtime Library Exception along with this program;
  18. // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  19. // <http://www.gnu.org/licenses/>.
  20. /** @file include/bits/mofunc_impl.h
  21. * This is an internal header file, included by other library headers.
  22. * Do not attempt to use it directly. @headername{functional}
  23. */
  24. #ifndef _GLIBCXX_MOF_CV
  25. # define _GLIBCXX_MOF_CV
  26. #endif
  27. #ifdef _GLIBCXX_MOF_REF
  28. # define _GLIBCXX_MOF_INV_QUALS _GLIBCXX_MOF_CV _GLIBCXX_MOF_REF
  29. #else
  30. # define _GLIBCXX_MOF_REF
  31. # define _GLIBCXX_MOF_INV_QUALS _GLIBCXX_MOF_CV &
  32. #endif
  33. #define _GLIBCXX_MOF_CV_REF _GLIBCXX_MOF_CV _GLIBCXX_MOF_REF
  34. namespace std _GLIBCXX_VISIBILITY(default)
  35. {
  36. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  37. /**
  38. * @brief Polymorphic function wrapper.
  39. * @ingroup functors
  40. * @since C++23
  41. * @headername functional
  42. *
  43. * The `std::move_only_function` class template is a call wrapper similar
  44. * to * `std::function`, but does not require the stored target function
  45. * to be copyable.
  46. *
  47. * It also supports const-qualification, ref-qualification, and
  48. * no-throw guarantees. The qualifications and exception-specification
  49. * of the `move_only_function::operator()` member function are respected
  50. * when invoking the target function.
  51. *
  52. */
  53. template<typename _Res, typename... _ArgTypes, bool _Noex>
  54. class move_only_function<_Res(_ArgTypes...) _GLIBCXX_MOF_CV
  55. _GLIBCXX_MOF_REF noexcept(_Noex)>
  56. : _Mofunc_base
  57. {
  58. template<typename _Tp>
  59. using __callable
  60. = __conditional_t<_Noex,
  61. is_nothrow_invocable_r<_Res, _Tp, _ArgTypes...>,
  62. is_invocable_r<_Res, _Tp, _ArgTypes...>>;
  63. // [func.wrap.mov.con]/1 is-callable-from<VT>
  64. template<typename _Vt>
  65. static constexpr bool __is_callable_from
  66. = __and_v<__callable<_Vt _GLIBCXX_MOF_CV_REF>,
  67. __callable<_Vt _GLIBCXX_MOF_INV_QUALS>>;
  68. public:
  69. using result_type = _Res;
  70. /// Creates an empty object.
  71. move_only_function() noexcept { }
  72. /// Creates an empty object.
  73. move_only_function(nullptr_t) noexcept { }
  74. /// Moves the target object, leaving the source empty.
  75. move_only_function(move_only_function&& __x) noexcept
  76. : _Mofunc_base(static_cast<_Mofunc_base&&>(__x)),
  77. _M_invoke(std::__exchange(__x._M_invoke, nullptr))
  78. { }
  79. /// Stores a target object initialized from the argument.
  80. template<typename _Fn, typename _Vt = decay_t<_Fn>>
  81. requires (!is_same_v<_Vt, move_only_function>)
  82. && (!__is_in_place_type_v<_Vt>) && __is_callable_from<_Vt>
  83. move_only_function(_Fn&& __f) noexcept(_S_nothrow_init<_Vt, _Fn>())
  84. {
  85. if constexpr (is_function_v<remove_pointer_t<_Vt>>
  86. || is_member_pointer_v<_Vt>
  87. || __is_move_only_function_v<_Vt>)
  88. {
  89. if (__f == nullptr)
  90. return;
  91. }
  92. _M_init<_Vt>(std::forward<_Fn>(__f));
  93. _M_invoke = &_S_invoke<_Vt>;
  94. }
  95. /// Stores a target object initialized from the arguments.
  96. template<typename _Tp, typename... _Args>
  97. requires is_constructible_v<_Tp, _Args...>
  98. && __is_callable_from<_Tp>
  99. explicit
  100. move_only_function(in_place_type_t<_Tp>, _Args&&... __args)
  101. noexcept(_S_nothrow_init<_Tp, _Args...>())
  102. : _M_invoke(&_S_invoke<_Tp>)
  103. {
  104. static_assert(is_same_v<decay_t<_Tp>, _Tp>);
  105. _M_init<_Tp>(std::forward<_Args>(__args)...);
  106. }
  107. /// Stores a target object initialized from the arguments.
  108. template<typename _Tp, typename _Up, typename... _Args>
  109. requires is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>
  110. && __is_callable_from<_Tp>
  111. explicit
  112. move_only_function(in_place_type_t<_Tp>, initializer_list<_Up> __il,
  113. _Args&&... __args)
  114. noexcept(_S_nothrow_init<_Tp, initializer_list<_Up>&, _Args...>())
  115. : _M_invoke(&_S_invoke<_Tp>)
  116. {
  117. static_assert(is_same_v<decay_t<_Tp>, _Tp>);
  118. _M_init<_Tp>(__il, std::forward<_Args>(__args)...);
  119. }
  120. /// Stores a new target object, leaving `x` empty.
  121. move_only_function&
  122. operator=(move_only_function&& __x) noexcept
  123. {
  124. _Mofunc_base::operator=(static_cast<_Mofunc_base&&>(__x));
  125. _M_invoke = std::__exchange(__x._M_invoke, nullptr);
  126. return *this;
  127. }
  128. /// Destroys the target object (if any).
  129. move_only_function&
  130. operator=(nullptr_t) noexcept
  131. {
  132. _Mofunc_base::operator=(nullptr);
  133. _M_invoke = nullptr;
  134. return *this;
  135. }
  136. /// Stores a new target object, initialized from the argument.
  137. template<typename _Fn>
  138. requires is_constructible_v<move_only_function, _Fn>
  139. move_only_function&
  140. operator=(_Fn&& __f)
  141. noexcept(is_nothrow_constructible_v<move_only_function, _Fn>)
  142. {
  143. move_only_function(std::forward<_Fn>(__f)).swap(*this);
  144. return *this;
  145. }
  146. ~move_only_function() = default;
  147. /// True if a target object is present, false otherwise.
  148. explicit operator bool() const noexcept { return _M_invoke != nullptr; }
  149. /** Invoke the target object.
  150. *
  151. * The target object will be invoked using the supplied arguments,
  152. * and as an lvalue or rvalue, and as const or non-const, as dictated
  153. * by the template arguments of the `move_only_function` specialization.
  154. *
  155. * @pre Must not be empty.
  156. */
  157. _Res
  158. operator()(_ArgTypes... __args) _GLIBCXX_MOF_CV_REF noexcept(_Noex)
  159. {
  160. __glibcxx_assert(*this != nullptr);
  161. return _M_invoke(this, std::forward<_ArgTypes>(__args)...);
  162. }
  163. /// Exchange the target objects (if any).
  164. void
  165. swap(move_only_function& __x) noexcept
  166. {
  167. _Mofunc_base::swap(__x);
  168. std::swap(_M_invoke, __x._M_invoke);
  169. }
  170. /// Exchange the target objects (if any).
  171. friend void
  172. swap(move_only_function& __x, move_only_function& __y) noexcept
  173. { __x.swap(__y); }
  174. /// Check for emptiness by comparing with `nullptr`.
  175. friend bool
  176. operator==(const move_only_function& __x, nullptr_t) noexcept
  177. { return __x._M_invoke == nullptr; }
  178. private:
  179. template<typename _Tp>
  180. using __param_t
  181. = __conditional_t<is_trivially_copyable_v<_Tp>
  182. && sizeof(_Tp) <= sizeof(long),
  183. _Tp, _Tp&&>;
  184. using _Invoker = _Res (*)(_Mofunc_base _GLIBCXX_MOF_CV*,
  185. __param_t<_ArgTypes>...) noexcept(_Noex);
  186. template<typename _Tp>
  187. static _Res
  188. _S_invoke(_Mofunc_base _GLIBCXX_MOF_CV* __self,
  189. __param_t<_ArgTypes>... __args) noexcept(_Noex)
  190. {
  191. using _TpCv = _Tp _GLIBCXX_MOF_CV;
  192. using _TpInv = _Tp _GLIBCXX_MOF_INV_QUALS;
  193. return std::__invoke_r<_Res>(
  194. std::forward<_TpInv>(*_S_access<_TpCv>(__self)),
  195. std::forward<__param_t<_ArgTypes>>(__args)...);
  196. }
  197. _Invoker _M_invoke = nullptr;
  198. };
  199. #undef _GLIBCXX_MOF_CV_REF
  200. #undef _GLIBCXX_MOF_CV
  201. #undef _GLIBCXX_MOF_REF
  202. #undef _GLIBCXX_MOF_INV_QUALS
  203. _GLIBCXX_END_NAMESPACE_VERSION
  204. } // namespace std