libstdc++
mofunc_impl.h
Go to the documentation of this file.
1 // Implementation of std::move_only_function -*- C++ -*-
2 
3 // Copyright The GNU Toolchain Authors.
4 //
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
9 // any later version.
10 
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
19 
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
24 
25 /** @file include/bits/mofunc_impl.h
26  * This is an internal header file, included by other library headers.
27  * Do not attempt to use it directly. @headername{functional}
28  */
29 
30 #ifndef _GLIBCXX_MOF_CV
31 # define _GLIBCXX_MOF_CV
32 #endif
33 
34 #ifdef _GLIBCXX_MOF_REF
35 # define _GLIBCXX_MOF_INV_QUALS _GLIBCXX_MOF_CV _GLIBCXX_MOF_REF
36 #else
37 # define _GLIBCXX_MOF_REF
38 # define _GLIBCXX_MOF_INV_QUALS _GLIBCXX_MOF_CV &
39 #endif
40 
41 #define _GLIBCXX_MOF_CV_REF _GLIBCXX_MOF_CV _GLIBCXX_MOF_REF
42 
43 namespace std _GLIBCXX_VISIBILITY(default)
44 {
45 _GLIBCXX_BEGIN_NAMESPACE_VERSION
46 
47  /**
48  * @brief Polymorphic function wrapper.
49  * @ingroup functors
50  * @since C++23
51  * @headerfile functional
52  *
53  * The `std::move_only_function` class template is a call wrapper similar
54  * to `std::function`, but does not require the stored target function
55  * to be copyable.
56  *
57  * It also supports const-qualification, ref-qualification, and
58  * no-throw guarantees. The qualifications and exception-specification
59  * of the `move_only_function::operator()` member function are respected
60  * when invoking the target function.
61  */
62  template<typename _Res, typename... _ArgTypes, bool _Noex>
63  class move_only_function<_Res(_ArgTypes...) _GLIBCXX_MOF_CV
64  _GLIBCXX_MOF_REF noexcept(_Noex)>
65  : __polyfunc::_Mo_base
66  {
67  static_assert(
68  (std::__is_complete_or_unbounded(__type_identity<_ArgTypes>()) && ...),
69  "each parameter type must be a complete class");
70 
71  using _Base = __polyfunc::_Mo_base;
72  using _Invoker = __polyfunc::_Invoker<_Noex, _Res, _ArgTypes...>;
73  using _Signature = _Invoker::_Signature;
74 
75  template<typename _Tp>
76  using __callable
77  = __conditional_t<_Noex,
78  is_nothrow_invocable_r<_Res, _Tp, _ArgTypes...>,
79  is_invocable_r<_Res, _Tp, _ArgTypes...>>;
80 
81  // [func.wrap.mov.con]/1 is-callable-from<VT>
82  template<typename _Vt>
83  static constexpr bool __is_callable_from
84  = __and_v<__callable<_Vt _GLIBCXX_MOF_CV_REF>,
85  __callable<_Vt _GLIBCXX_MOF_INV_QUALS>>;
86 
87  public:
88  using result_type = _Res;
89 
90  /// Creates an empty object.
91  move_only_function() noexcept { }
92 
93  /// Creates an empty object.
94  move_only_function(nullptr_t) noexcept { }
95 
96  /// Moves the target object, leaving the source empty.
97  move_only_function(move_only_function&& __x) noexcept
98  : _Base(static_cast<_Base&&>(__x)),
99  _M_invoke(std::__exchange(__x._M_invoke, nullptr))
100  { }
101 
102  /// Stores a target object initialized from the argument.
103  template<typename _Fn, typename _Vt = decay_t<_Fn>>
104  requires (!is_same_v<_Vt, move_only_function>)
105  && (!__is_in_place_type_v<_Vt>) && __is_callable_from<_Vt>
106  move_only_function(_Fn&& __f) noexcept(_S_nothrow_init<_Vt, _Fn>())
107  {
108  // _GLIBCXX_RESOLVE_LIB_DEFECTS
109  // 4255. move_only_function constructor should recognize empty
110  // copyable_functions
111  if constexpr (is_function_v<remove_pointer_t<_Vt>>
112  || is_member_pointer_v<_Vt>
113  || __is_polymorphic_function_v<_Vt>)
114  {
115  if (__f == nullptr)
116  return;
117  }
118 
119  if constexpr (__is_polymorphic_function_v<_Vt>
120  && __polyfunc::__is_invoker_convertible<_Vt, move_only_function>())
121  {
122  // Handle cases where _Fn is const reference to copyable_function,
123  // by firstly creating temporary and moving from it.
124  _Vt __tmp(std::forward<_Fn>(__f));
125  _M_move(__polyfunc::__base_of(__tmp));
126  _M_invoke = std::__exchange(__polyfunc::__invoker_of(__tmp), nullptr);
127  }
128  else
129  {
130  _M_init<_Vt>(std::forward<_Fn>(__f));
131  _M_invoke = _Invoker::template _S_storage<_Vt _GLIBCXX_MOF_INV_QUALS>();
132  }
133  }
134 
135  /// Stores a target object initialized from the arguments.
136  template<typename _Tp, typename... _Args>
137  requires is_constructible_v<_Tp, _Args...>
138  && __is_callable_from<_Tp>
139  explicit
140  move_only_function(in_place_type_t<_Tp>, _Args&&... __args)
141  noexcept(_S_nothrow_init<_Tp, _Args...>())
142  : _M_invoke(_Invoker::template _S_storage<_Tp _GLIBCXX_MOF_INV_QUALS>())
143  {
144  static_assert(is_same_v<decay_t<_Tp>, _Tp>);
145  _M_init<_Tp>(std::forward<_Args>(__args)...);
146  }
147 
148  /// Stores a target object initialized from the arguments.
149  template<typename _Tp, typename _Up, typename... _Args>
150  requires is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>
151  && __is_callable_from<_Tp>
152  explicit
153  move_only_function(in_place_type_t<_Tp>, initializer_list<_Up> __il,
154  _Args&&... __args)
155  noexcept(_S_nothrow_init<_Tp, initializer_list<_Up>&, _Args...>())
156  : _M_invoke(_Invoker::template _S_storage<_Tp _GLIBCXX_MOF_INV_QUALS>())
157  {
158  static_assert(is_same_v<decay_t<_Tp>, _Tp>);
159  _M_init<_Tp>(__il, std::forward<_Args>(__args)...);
160  }
161 
162  /// Stores a new target object, leaving `x` empty.
163  move_only_function&
164  operator=(move_only_function&& __x) noexcept
165  {
166  // Standard requires support of self assigment, by specifying it as
167  // copy and swap.
168  if (this != std::addressof(__x)) [[likely]]
169  {
170  _Base::operator=(static_cast<_Base&&>(__x));
171  _M_invoke = std::__exchange(__x._M_invoke, nullptr);
172  }
173  return *this;
174  }
175 
176  /// Destroys the target object (if any).
177  move_only_function&
178  operator=(nullptr_t) noexcept
179  {
180  _M_reset();
181  _M_invoke = nullptr;
182  return *this;
183  }
184 
185  /// Stores a new target object, initialized from the argument.
186  template<typename _Fn>
187  requires is_constructible_v<move_only_function, _Fn>
188  move_only_function&
189  operator=(_Fn&& __f)
190  noexcept(is_nothrow_constructible_v<move_only_function, _Fn>)
191  {
192  move_only_function(std::forward<_Fn>(__f)).swap(*this);
193  return *this;
194  }
195 
196  ~move_only_function() = default;
197 
198  /// True if a target object is present, false otherwise.
199  explicit operator bool() const noexcept
200  { return _M_invoke != nullptr; }
201 
202  /** Invoke the target object.
203  *
204  * The target object will be invoked using the supplied arguments,
205  * and as an lvalue or rvalue, and as const or non-const, as dictated
206  * by the template arguments of the `move_only_function` specialization.
207  *
208  * @pre Must not be empty.
209  */
210  _Res
211  operator()(_ArgTypes... __args) _GLIBCXX_MOF_CV_REF noexcept(_Noex)
212  {
213  __glibcxx_assert(*this != nullptr);
214  return _M_invoke(this->_M_storage, std::forward<_ArgTypes>(__args)...);
215  }
216 
217  /// Exchange the target objects (if any).
218  void
219  swap(move_only_function& __x) noexcept
220  {
221  _Base::swap(__x);
222  std::swap(_M_invoke, __x._M_invoke);
223  }
224 
225  /// Exchange the target objects (if any).
226  friend void
227  swap(move_only_function& __x, move_only_function& __y) noexcept
228  { __x.swap(__y); }
229 
230  /// Check for emptiness by comparing with `nullptr`.
231  friend bool
232  operator==(const move_only_function& __x, nullptr_t) noexcept
233  { return __x._M_invoke == nullptr; }
234 
235  private:
236  typename _Invoker::__storage_func_t _M_invoke = nullptr;
237 
238  template<typename _Func>
239  friend auto&
240  __polyfunc::__invoker_of(_Func&) noexcept;
241 
242  template<typename _Func>
243  friend auto&
244  __polyfunc::__base_of(_Func&) noexcept;
245 
246  template<typename _Dst, typename _Src>
247  friend consteval bool
248  __polyfunc::__is_invoker_convertible() noexcept;
249  };
250 
251 #undef _GLIBCXX_MOF_CV_REF
252 #undef _GLIBCXX_MOF_CV
253 #undef _GLIBCXX_MOF_REF
254 #undef _GLIBCXX_MOF_INV_QUALS
255 
256 _GLIBCXX_END_NAMESPACE_VERSION
257 } // namespace std
std::addressof
constexpr _Tp * addressof(_Tp &__r) noexcept
Returns the actual address of the object or function referenced by r, even in the presence of an over...
Definition: move.h:176
std::decay_t
typename decay< _Tp >::type decay_t
Alias template for decay.
Definition: type_traits:2938
std::move_only_function< _Res(_ArgTypes...) _GLIBCXX_MOF_CV noexcept(_Noex)>::move_only_function
move_only_function() noexcept
Creates an empty object.
Definition: mofunc_impl.h:91
std::move_only_function< _Res(_ArgTypes...) _GLIBCXX_MOF_CV noexcept(_Noex)>::move_only_function
move_only_function(nullptr_t) noexcept
Creates an empty object.
Definition: mofunc_impl.h:94
std::move_only_function< _Res(_ArgTypes...) _GLIBCXX_MOF_CV noexcept(_Noex)>::move_only_function
move_only_function(move_only_function &&__x) noexcept
Moves the target object, leaving the source empty.
Definition: mofunc_impl.h:97
std::initializer_list
initializer_list
Definition: initializer_list:47
std
ISO C++ entities toplevel namespace is std.
std::remove_pointer_t
typename remove_pointer< _Tp >::type remove_pointer_t
Alias template for remove_pointer.
Definition: type_traits:2354
std::move_only_function< _Res(_ArgTypes...) _GLIBCXX_MOF_CV noexcept(_Noex)>::requires
requires(!is_same_v< _Vt, move_only_function >) &&(!__is_in_place_type_v< _Vt >) &&__is_callable_from< _Vt > move_only_function(_Fn &&__f) noexcept(_S_nothrow_init< _Vt, _Fn >())
Stores a target object initialized from the argument.
Definition: mofunc_impl.h:104