libstdc++
funcref_impl.h
Go to the documentation of this file.
1// Implementation of std::function_ref -*- 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/funcref_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
34namespace std _GLIBCXX_VISIBILITY(default)
35{
36_GLIBCXX_BEGIN_NAMESPACE_VERSION
37
38 /// @cond undocumented
39 namespace __polyfunc
40 {
41 template<bool _Noex, typename _Ret, typename _Class, typename... _Args>
42 struct __skip_first_arg<_Ret(_Class::*)(_Args...) _GLIBCXX_MOF_CV
43 noexcept(_Noex)>
44 { using type = _Ret(_Args...) noexcept(_Noex); };
45
46 template<bool _Noex, typename _Ret, typename _Class, typename... _Args>
47 struct __skip_first_arg<_Ret(_Class::*)(_Args...) _GLIBCXX_MOF_CV&
48 noexcept(_Noex)>
49 { using type = _Ret(_Args...) noexcept(_Noex); };
50 } // namespace __polyfunc
51 /// @endcond
52
53 /**
54 * @brief Non-owning polymorphic function wrapper.
55 * @ingroup functors
56 * @since C++26
57 * @headerfile functional
58 *
59 * The `std::function_ref` class template is a non-owning call wrapper,
60 * that refers to a bound object. Using function_ref outside of the lifetime
61 * of the bound object has undefined behavior.
62 *
63 * It supports const-qualification and no-throw guarantees. The
64 * qualifications and exception-specification of the signature are respected
65 * when invoking the reference function.
66 */
67 template<typename _Res, typename... _ArgTypes, bool _Noex>
68 class function_ref<_Res(_ArgTypes...) _GLIBCXX_MOF_CV
69 noexcept(_Noex)>
70 : __polyfunc::_Ref_base
71 {
72 static_assert(
73 (std::__is_complete_or_unbounded(__type_identity<_ArgTypes>()) && ...),
74 "each parameter type must be a complete class");
75
76 using _Base = __polyfunc::_Ref_base;
77 using _Invoker = __polyfunc::_Invoker<_Noex, _Res, _ArgTypes...>;
78 using _ArgsSignature = _Res(_ArgTypes...) noexcept(_Noex);
79 using _TargetQuals = int _GLIBCXX_MOF_CV&;
80
81 // [func.wrap.ref.ctor]/1 is-invokable-using
82 template<typename... _Tps>
83 static constexpr bool __is_invocable_using
84 = __conditional_t<_Noex,
85 is_nothrow_invocable_r<_Res, _Tps..., _ArgTypes...>,
86 is_invocable_r<_Res, _Tps..., _ArgTypes...>>::value;
87
88 public:
89 /// Target and bound object is function pointed by parameter.
90 template<typename _Fn>
91 requires is_function_v<_Fn> && __is_invocable_using<_Fn*>
92 function_ref(_Fn* __fn) noexcept
93 {
94 __glibcxx_assert(__fn != nullptr);
95 _M_init(__fn);
96 _M_invoke = _Invoker::template _S_ptrs<_Fn*>();
97 }
98
99 /// Target and bound object is object referenced by parameter.
100 template<typename _Fn, typename _Vt = remove_reference_t<_Fn>>
101 requires (!is_same_v<remove_cv_t<_Vt>, function_ref>)
102 && (!is_member_pointer_v<_Vt>)
103 // We deviate from standard by having this condition, that forces
104 // function references to use _Fn* constructors. This simplies
105 // implementation and provide better diagnostic when used in
106 // constant expression (above constructor is not constexpr).
107 && (!is_function_v<_Vt>)
108 && __is_invocable_using<_Vt _GLIBCXX_MOF_CV&>
109 constexpr
110 function_ref(_Fn&& __f) noexcept
111 {
112 using _Fd = remove_cv_t<_Vt>;
113 if constexpr (__is_std_op_wrapper<_Fd>)
114 _M_invoke = _Invoker::template _S_nttp<_Fd{}>;
115 else if constexpr (requires (_ArgTypes&&... __args) {
116 _Fd::operator()(std::forward<_ArgTypes>(__args)...);
117 })
118 _M_invoke = _Invoker::template _S_static<_Fd>;
119 else if constexpr (__is_function_ref_v<_Fd>
120 && __polyfunc::__is_invoker_convertible<_Fd, function_ref>())
121 {
122 _Base::operator=(__polyfunc::__base_of(__f));
123 _M_invoke = __polyfunc::__invoker_of(__f);
124 }
125 else
126 {
127 _M_init(std::addressof(__f));
128 _M_invoke = _Invoker::template _S_ptrs<_Vt _GLIBCXX_MOF_CV&>();
129 }
130 }
131
132 // _GLIBCXX_RESOLVE_LIB_DEFECTS
133 // 4256. Incorrect constrains for function_ref constructors from nontype
134 /// Target object is __fn. There is no bound object.
135 template<auto __cwfn, typename _Fn>
136 requires __is_invocable_using<const _Fn&>
137 constexpr
138 function_ref(constant_wrapper<__cwfn, _Fn>) noexcept
139 {
140 constexpr const _Fn& __fn = constant_wrapper<__cwfn, _Fn>::value;
141 if constexpr (sizeof...(_ArgTypes) > 0)
142 if constexpr ((... && _ConstExprParam<remove_cvref_t<_ArgTypes>>))
143 static_assert(!requires {
144 typename constant_wrapper<
145 std::__invoke(__fn, remove_cvref_t<_ArgTypes>::value...)>;
146 }, "cw<fn>(args...) should be equivalent to fn(args...)");
147
148 if constexpr (is_pointer_v<_Fn> || is_member_pointer_v<_Fn>)
149 static_assert(__fn != nullptr);
150
151 _M_invoke = &_Invoker::template _S_nttp<__fn>;
152 }
153
154 /// Target object is equivalent to std::bind_front<_fn>(std::ref(__ref)).
155 /// Bound object is object referenced by second parameter.
156 template<auto __cwfn, typename _Fn, typename _Up,
157 typename _Td = remove_reference_t<_Up>>
158 requires (!is_rvalue_reference_v<_Up&&>)
159 && __is_invocable_using<const _Fn&, _Td _GLIBCXX_MOF_CV&>
160 constexpr
161 function_ref(constant_wrapper<__cwfn, _Fn>, _Up&& __ref) noexcept
162 {
163 constexpr const _Fn& __fn = constant_wrapper<__cwfn, _Fn>::value;
164 if constexpr (is_pointer_v<_Fn> || is_member_pointer_v<_Fn>)
165 static_assert(__fn != nullptr);
166
167 _M_init(std::addressof(__ref));
168 if constexpr (is_member_pointer_v<_Fn>
170 // N.B. invoking member pointer on lvalue produces the same effects,
171 // as invoking it on pointer to that lvalue.
172 _M_invoke = &_Invoker::template _S_bind_ptr<__fn, _Td _GLIBCXX_MOF_CV>;
173 else
174 _M_invoke = &_Invoker::template _S_bind_ref<__fn, _Td _GLIBCXX_MOF_CV&>;
175 }
176
177 /// Target object is equivalent to std::bind_front<_fn>(__ptr).
178 /// Bound object is object pointed by second parameter (if any).
179 template< auto __cwfn, typename _Fn, typename _Td>
180 requires __is_invocable_using<const _Fn&, _Td _GLIBCXX_MOF_CV*>
181 constexpr
182 function_ref(constant_wrapper<__cwfn, _Fn>, _Td _GLIBCXX_MOF_CV* __ptr) noexcept
183 {
184 constexpr const _Fn& __fn = constant_wrapper<__cwfn, _Fn>::value;
185 if constexpr (is_pointer_v<_Fn> || is_member_pointer_v<_Fn>)
186 static_assert(__fn != nullptr);
187 if constexpr (is_member_pointer_v<_Fn>)
188 __glibcxx_assert(__ptr != nullptr);
189
190 _M_init(__ptr);
191 _M_invoke = &_Invoker::template _S_bind_ptr<__fn, _Td _GLIBCXX_MOF_CV>;
192 }
193
194 template<typename _Tp>
195 requires (!is_same_v<_Tp, function_ref>)
196 && (!is_pointer_v<_Tp>)
197 && (!__is_constant_wrapper_v<_Tp>)
198 && (!__polyfunc::__is_funcref_assignable<function_ref, _Tp>())
199 function_ref&
200 operator=(_Tp) = delete;
201
202 /** Invoke the target object.
203 *
204 * The bound object will be invoked using the supplied arguments,
205 * and as const or non-const, as dictated by the template arguments
206 * of the `function_ref` specialization.
207 */
208 _Res
209 operator()(_ArgTypes... __args) const noexcept(_Noex)
210 { return _M_invoke(_M_ptrs, std::forward<_ArgTypes>(__args)...); }
211
212 private:
213 typename _Invoker::__ptrs_func_t _M_invoke;
214
215 template<typename _Func>
216 friend constexpr auto&
217 __polyfunc::__invoker_of(_Func&) noexcept;
218
219 template<typename _Func>
220 friend constexpr auto&
221 __polyfunc::__base_of(_Func&) noexcept;
222
223 template<typename _Src, typename _Dst>
224 friend consteval bool
225 __polyfunc::__is_invoker_convertible() noexcept;
226
227 template<typename _Dst, typename _Src>
228 friend consteval bool
229 __polyfunc::__is_funcref_assignable() noexcept;
230 };
231
232#undef _GLIBCXX_MOF_CV
233
234_GLIBCXX_END_NAMESPACE_VERSION
235} // namespace std
typename remove_reference< _Tp >::type remove_reference_t
Alias template for remove_reference.
Definition type_traits:1890
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
constexpr __invoke_result< _Callable, _Args... >::type __invoke(_Callable &&__fn, _Args &&... __args) noexcept(__is_nothrow_invocable< _Callable, _Args... >::value)
Invoke a callable object.
Definition invoke.h:92
constexpr _Tp && forward(typename std::remove_reference< _Tp >::type &__t) noexcept
Forward an lvalue.
Definition move.h:72
ISO C++ entities toplevel namespace is std.
constexpr function_ref(_Fn &&__f) noexcept
Target and bound object is object referenced by parameter.
constexpr function_ref(constant_wrapper< __cwfn, _Fn >, _Td _GLIBCXX_MOF_CV *__ptr) noexcept
Target object is equivalent to std::bind_front<_fn>(__ptr). Bound object is object pointed by second ...
_Res operator()(_ArgTypes... __args) const noexcept(_Noex)
constexpr function_ref(constant_wrapper< __cwfn, _Fn >) noexcept
Target object is __fn. There is no bound object.
constexpr function_ref(constant_wrapper< __cwfn, _Fn >, _Up &&__ref) noexcept
Target object is equivalent to std::bind_front<_fn>(std::ref(__ref)). Bound object is object referenc...
function_ref(_Fn *__fn) noexcept
Target and bound object is function pointed by parameter.
[concept.same], concept same_as
Definition concepts:65