@@ -152,6 +152,11 @@ template <class D, class T, bool NE, class R, class... Args>
152
152
concept invocable_dispatch = requires { typename D::template invoker<T>; } &&
153
153
is_invoker_well_formed<
154
154
typename D::template invoker<T>, T, NE, R, Args...>();
155
+ template <class D , class P , bool NE, class R , class ... Args>
156
+ concept invocable_dispatch_ptr = invocable_dispatch<
157
+ D, typename ptr_traits<P>::target_type, NE, R, Args...> ||
158
+ invocable_dispatch<D, const P, NE, R, Args...> ||
159
+ invocable_dispatch<D, void , NE, R, Args...>;
155
160
156
161
template <bool NE, class R , class ... Args>
157
162
using func_ptr_t = std::conditional_t <
@@ -166,14 +171,20 @@ R invoke_dispatch(Args&&... args) {
166
171
}
167
172
}
168
173
template <class P , class F , class R , class ... Args>
169
- R invocation_dispatcher (const char * self, Args... args)
174
+ R invocation_dispatcher_ref (const char * self, Args... args)
170
175
noexcept (is_invoker_well_formed<
171
176
F, typename ptr_traits<P>::target_type, true , R, Args...>()) {
172
177
return invoke_dispatch<F, R>(ptr_traits<P>::dereference (*std::launder (
173
178
reinterpret_cast <const P*>(self))), std::forward<Args>(args)...);
174
179
}
180
+ template <class P , class F , class R , class ... Args>
181
+ R invocation_dispatcher_ptr (const char * self, Args... args)
182
+ noexcept (is_invoker_well_formed<F, const P, true , R, Args...>()) {
183
+ return invoke_dispatch<F, R>(*std::launder (reinterpret_cast <const P*>(self)),
184
+ std::forward<Args>(args)...);
185
+ }
175
186
template <class F , class R , class ... Args>
176
- R invocation_default_dispatcher (const char *, Args... args)
187
+ R invocation_dispatcher_void (const char *, Args... args)
177
188
noexcept (is_invoker_well_formed<F, void , true , R, Args...>())
178
189
{ return invoke_dispatch<F, R>(std::forward<Args>(args)...); }
179
190
template <class P >
@@ -208,19 +219,21 @@ struct overload_traits_impl : applicable_traits {
208
219
static constexpr func_ptr_t <NE, R, const char *, Args...> get () {
209
220
if constexpr (invocable_dispatch<
210
221
D, typename ptr_traits<P>::target_type, NE, R, Args...>) {
211
- return &invocation_dispatcher <P, typename D::template invoker<
222
+ return &invocation_dispatcher_ref <P, typename D::template invoker<
212
223
typename ptr_traits<P>::target_type>, R, Args...>;
224
+ } else if constexpr (invocable_dispatch<D, const P, NE, R, Args...>) {
225
+ return &invocation_dispatcher_ptr<
226
+ P, typename D::template invoker<const P>, R, Args...>;
213
227
} else {
214
- return &invocation_default_dispatcher <
228
+ return &invocation_dispatcher_void <
215
229
typename D::template invoker<void >, R, Args...>;
216
230
}
217
231
}
218
232
};
219
233
struct resolver { func_ptr_t <NE, R, Args...> operator ()(Args...); };
220
234
template <class D , class P >
221
- static constexpr bool applicable_ptr = invocable_dispatch<
222
- D, typename ptr_traits<P>::target_type, NE, R, Args...> ||
223
- invocable_dispatch<D, void , NE, R, Args...>;
235
+ static constexpr bool applicable_ptr =
236
+ invocable_dispatch_ptr<D, P, NE, R, Args...>;
224
237
static constexpr bool is_noexcept = NE;
225
238
};
226
239
template <class O > struct overload_traits : inapplicable_traits {};
0 commit comments