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  : _Mofunc_base
66  {
67  template<typename _Tp>
68  using __callable
69  = __conditional_t<_Noex,
70  is_nothrow_invocable_r<_Res, _Tp, _ArgTypes...>,
71  is_invocable_r<_Res, _Tp, _ArgTypes...>>;
72 
73  // [func.wrap.mov.con]/1 is-callable-from<VT>
74  template<typename _Vt>
75  static constexpr bool __is_callable_from
76  = __and_v<__callable<_Vt _GLIBCXX_MOF_CV_REF>,
77  __callable<_Vt _GLIBCXX_MOF_INV_QUALS>>;
78 
79  public:
80  using result_type = _Res;
81 
82  /// Creates an empty object.
83  move_only_function() noexcept { }
84 
85  /// Creates an empty object.
86  move_only_function(nullptr_t) noexcept { }
87 
88  /// Moves the target object, leaving the source empty.
89  move_only_function(move_only_function&& __x) noexcept
90  : _Mofunc_base(static_cast<_Mofunc_base&&>(__x)),
91  _M_invoke(std::__exchange(__x._M_invoke, nullptr))
92  { }
93 
94  /// Stores a target object initialized from the argument.
95  template<typename _Fn, typename _Vt = decay_t<_Fn>>
96  requires (!is_same_v<_Vt, move_only_function>)
97  && (!__is_in_place_type_v<_Vt>) && __is_callable_from<_Vt>
98  move_only_function(_Fn&& __f) noexcept(_S_nothrow_init<_Vt, _Fn>())
99  {
100  if constexpr (is_function_v<remove_pointer_t<_Vt>>
101  || is_member_pointer_v<_Vt>
102  || __is_move_only_function_v<_Vt>)
103  {
104  if (__f == nullptr)
105  return;
106  }
107  _M_init<_Vt>(std::forward<_Fn>(__f));
108  _M_invoke = &_S_invoke<_Vt>;
109  }
110 
111  /// Stores a target object initialized from the arguments.
112  template<typename _Tp, typename... _Args>
113  requires is_constructible_v<_Tp, _Args...>
114  && __is_callable_from<_Tp>
115  explicit
116  move_only_function(in_place_type_t<_Tp>, _Args&&... __args)
117  noexcept(_S_nothrow_init<_Tp, _Args...>())
118  : _M_invoke(&_S_invoke<_Tp>)
119  {
120  static_assert(is_same_v<decay_t<_Tp>, _Tp>);
121  _M_init<_Tp>(std::forward<_Args>(__args)...);
122  }
123 
124  /// Stores a target object initialized from the arguments.
125  template<typename _Tp, typename _Up, typename... _Args>
126  requires is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>
127  && __is_callable_from<_Tp>
128  explicit
129  move_only_function(in_place_type_t<_Tp>, initializer_list<_Up> __il,
130  _Args&&... __args)
131  noexcept(_S_nothrow_init<_Tp, initializer_list<_Up>&, _Args...>())
132  : _M_invoke(&_S_invoke<_Tp>)
133  {
134  static_assert(is_same_v<decay_t<_Tp>, _Tp>);
135  _M_init<_Tp>(__il, std::forward<_Args>(__args)...);
136  }
137 
138  /// Stores a new target object, leaving `x` empty.
139  move_only_function&
140  operator=(move_only_function&& __x) noexcept
141  {
142  _Mofunc_base::operator=(static_cast<_Mofunc_base&&>(__x));
143  _M_invoke = std::__exchange(__x._M_invoke, nullptr);
144  return *this;
145  }
146 
147  /// Destroys the target object (if any).
148  move_only_function&
149  operator=(nullptr_t) noexcept
150  {
151  _Mofunc_base::operator=(nullptr);
152  _M_invoke = nullptr;
153  return *this;
154  }
155 
156  /// Stores a new target object, initialized from the argument.
157  template<typename _Fn>
158  requires is_constructible_v<move_only_function, _Fn>
159  move_only_function&
160  operator=(_Fn&& __f)
161  noexcept(is_nothrow_constructible_v<move_only_function, _Fn>)
162  {
163  move_only_function(std::forward<_Fn>(__f)).swap(*this);
164  return *this;
165  }
166 
167  ~move_only_function() = default;
168 
169  /// True if a target object is present, false otherwise.
170  explicit operator bool() const noexcept { return _M_invoke != nullptr; }
171 
172  /** Invoke the target object.
173  *
174  * The target object will be invoked using the supplied arguments,
175  * and as an lvalue or rvalue, and as const or non-const, as dictated
176  * by the template arguments of the `move_only_function` specialization.
177  *
178  * @pre Must not be empty.
179  */
180  _Res
181  operator()(_ArgTypes... __args) _GLIBCXX_MOF_CV_REF noexcept(_Noex)
182  {
183  __glibcxx_assert(*this != nullptr);
184  return _M_invoke(this, std::forward<_ArgTypes>(__args)...);
185  }
186 
187  /// Exchange the target objects (if any).
188  void
189  swap(move_only_function& __x) noexcept
190  {
191  _Mofunc_base::swap(__x);
192  std::swap(_M_invoke, __x._M_invoke);
193  }
194 
195  /// Exchange the target objects (if any).
196  friend void
197  swap(move_only_function& __x, move_only_function& __y) noexcept
198  { __x.swap(__y); }
199 
200  /// Check for emptiness by comparing with `nullptr`.
201  friend bool
202  operator==(const move_only_function& __x, nullptr_t) noexcept
203  { return __x._M_invoke == nullptr; }
204 
205  private:
206  template<typename _Tp>
207  using __param_t = __conditional_t<is_scalar_v<_Tp>, _Tp, _Tp&&>;
208 
209  using _Invoker = _Res (*)(_Mofunc_base _GLIBCXX_MOF_CV*,
210  __param_t<_ArgTypes>...) noexcept(_Noex);
211 
212  template<typename _Tp>
213  static _Res
214  _S_invoke(_Mofunc_base _GLIBCXX_MOF_CV* __self,
215  __param_t<_ArgTypes>... __args) noexcept(_Noex)
216  {
217  using _TpCv = _Tp _GLIBCXX_MOF_CV;
218  using _TpInv = _Tp _GLIBCXX_MOF_INV_QUALS;
219  return std::__invoke_r<_Res>(
220  std::forward<_TpInv>(*_S_access<_TpCv>(__self)),
221  std::forward<__param_t<_ArgTypes>>(__args)...);
222  }
223 
224  _Invoker _M_invoke = nullptr;
225  };
226 
227 #undef _GLIBCXX_MOF_CV_REF
228 #undef _GLIBCXX_MOF_CV
229 #undef _GLIBCXX_MOF_REF
230 #undef _GLIBCXX_MOF_INV_QUALS
231 
232 _GLIBCXX_END_NAMESPACE_VERSION
233 } // namespace std
typename remove_pointer< _Tp >::type remove_pointer_t
Alias template for remove_pointer.
Definition: type_traits:2164
typename decay< _Tp >::type decay_t
Alias template for decay.
Definition: type_traits:2707
constexpr _Tp && forward(typename std::remove_reference< _Tp >::type &__t) noexcept
Forward an lvalue.
Definition: move.h:71
ISO C++ entities toplevel namespace is std.
initializer_list
move_only_function(move_only_function &&__x) noexcept
Moves the target object, leaving the source empty.
Definition: mofunc_impl.h:89
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:96