BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslstl_function_invokerutil.h
Go to the documentation of this file.
1/// @file bslstl_function_invokerutil.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslstl_function_invokerutil.h -*-C++-*-
8#ifndef INCLUDED_BSLSTL_FUNCTION_INVOKERUTIL
9#define INCLUDED_BSLSTL_FUNCTION_INVOKERUTIL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslstl_function_invokerutil bslstl_function_invokerutil
15/// @brief Provide invoker adaptors for `bsl::function`
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslstl
19/// @{
20/// @addtogroup bslstl_function_invokerutil
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslstl_function_invokerutil-purpose"> Purpose</a>
25/// * <a href="#bslstl_function_invokerutil-classes"> Classes </a>
26/// * <a href="#bslstl_function_invokerutil-description"> Description </a>
27/// * <a href="#bslstl_function_invokerutil-macros"> Macros </a>
28/// * <a href="#bslstl_function_invokerutil-return-value-of-function_invokerutil-invokerforfunc"> Return value of Function_InvokerUtil::invokerForFunc </a>
29/// * <a href="#bslstl_function_invokerutil-customization-point-function_invokerutilnullcheck"> Customization point Function_InvokerUtilNullCheck </a>
30///
31/// # Purpose {#bslstl_function_invokerutil-purpose}
32/// Provide invoker adaptors for `bsl::function`
33///
34/// # Classes {#bslstl_function_invokerutil-classes}
35///
36/// - Function_InvokerUtil: Utility for returning an appropriate invoker function
37/// - Function_InvokerUtilNullCheck: Customization point to detect null invocable
38///
39///@MACROS
40/// BSLSTL_FUNCTION_INVOKERUTIL_SUPPORT_IS_FUNC_INVOCABLE: defined if supported
41///
42/// @see bslstl_function
43///
44/// # Description {#bslstl_function_invokerutil-description}
45/// This component provides a struct, `Function_InvokerUtil`,
46/// containing a function template, `invokerForFunc`, that returns a pointer to
47/// a function that is used to invoke a callable object of a particular type.
48/// The returned type is custom-generated for each specific target type. This
49/// component is for private use only.
50///
51/// The client of this component, `bsl::function`, is a complex class that is
52/// templated in two ways:
53///
54/// 1. The class itself has a template parameter representing the prototype
55/// (argument and return types) of its call operator. E.g., type
56/// `bsl::function<int(char*)>` has member `int operator()(char*);`.
57/// 2. Several of its constructors take an argument of template parameter
58/// callable type and wrap it, using type erasure, so that the type of the
59/// wrapped target is not part of the type of the `bsl::function`.
60///
61/// Only the invocation mechanism needs both kinds of template parameters; other
62/// parts of `bsl::function` (e.g., `bslstl::Function_Rep`) concern themselves
63/// with only the callable object type, not with the prototype of the call
64/// operator. This component factors out most of that complexity so as to
65/// minimise code size, especially when using the `sim_cpp11_features.pl` script
66/// to simulate C++11 variadic templates in C++03.
67///
68/// The classes in this component are stateless and contain only static
69/// functions.
70///
71/// ## Macros {#bslstl_function_invokerutil-macros}
72///
73///
74/// If this component supports checking whether an object of an arbitrary
75/// non-cvref-qualified type is invocable under a particular prototype, the
76/// `BSLSTL_FUNCTION_INVOKERUTIL_SUPPORT_IS_FUNC_INVOCABLE` macro is defined,
77/// and it is not defined otherwise.
78///
79/// ## Return value of Function_InvokerUtil::invokerForFunc {#bslstl_function_invokerutil-return-value-of-function_invokerutil-invokerforfunc}
80///
81///
82/// The function pointer, `invoker_p`, returned by
83/// `Function_InvokerUtil::invokerForFunc<RET(ARG0, ARG1, ...)>` takes an
84/// argument of type `Function_Rep *` and zero or more argument types `ARG0`,
85/// `ARG1`, ..., as specified by the template argument. Calling
86/// `invoker_p(rep, arg0, arg1, ...)` gets the target, `f` from `rep` and
87/// invokes it with the supplied arguments. Invocation of `f` follows the
88/// definition of *INVOKE* in section [func.require] of the C++ standard. These
89/// rules are summarized in the following table:
90/// @code
91/// +----------------------------+-----------------------+
92/// | Type of target object, 'f' | Invocation expression |
93/// +============================+=======================+
94/// | Pointer to function or | f(arg0, arg1, ...) |
95/// | functor class | |
96/// +----------------------------+-----------------------+
97/// | Pointer to member function | (arg0X.*f)(arg1, ...) |
98/// +----------------------------+-----------------------+
99/// | pointer to data member | arg0X.*f |
100/// +----------------------------+-----------------------+
101/// @endcode
102/// The arguments to `f` must be implicitly convertible from the corresponding
103/// argument types `ARG0`, `ARG1`, ... and the return value of the call
104/// expression must be implicitly convertible to `RET`, unless `RET` is `void`.
105///
106/// In the case of a pointer to member function, `R (T::*f)(...)`, or pointer to
107/// data member `R T::*f`, `arg0X` is one of the following:
108///
109/// * `arg0` if `ARG0` is `T` or derived from `T`.
110/// * `arg0.get()` if `ARG0` is a specialization of @ref reference_wrapper .
111/// * `(*arg0)` if `ARG0` is a pointer type or pointer-like type (e.g., a smart
112/// pointer).
113///
114/// Note that, consistent with the C++ Standard definition of *INVOKE*, we
115/// consider pointer-to-member-function and pointer-to-data-member types to be
116/// "callable" even though, strictly speaking, they lack an `operator()`.
117///
118/// ## Customization point Function_InvokerUtilNullCheck {#bslstl_function_invokerutil-customization-point-function_invokerutilnullcheck}
119///
120///
121/// The class template, `Function_InvokerUtilNullCheck<T>` provides a single,
122/// `static` member function `isNull(const T& f)` that returns `true` iff `f`
123/// represents a "null value". By default,
124/// `Function_InvokerUtilNullCheck<T>::isNull` returns `true` iff `T` is a
125/// pointer or pointer-to-member type and has a null value. For non-pointer
126/// types, the primary template always returns `false`. However, other
127/// components can provide specializations of `Function_InvokerUtilNullCheck`
128/// that add the notion of "nullness" to other invocable types. In particular,
129/// `bslstl_function.h` specializes this template for `bsl::function` and
130/// `bdef_function.h` specializes this template for @ref bdef_function . In both
131/// cases, a function object is considered null if it is empty, i.e., it does
132/// not wrap an invocable object. Although it is theoretically possible to
133/// specialize `Function_InvokerUtilNullCheck` for types not related to
134/// `bsl::function`, doing so would go outside of the behavior of the standard
135/// `std::function` type that `bsl::function` is emulating. For this reason,
136/// `Function_InvokerUtilNullCheck` is tucked away in this private component for
137/// use only through explicit collaboration.
138/// @}
139/** @} */
140/** @} */
141
142/** @addtogroup bsl
143 * @{
144 */
145/** @addtogroup bslstl
146 * @{
147 */
148/** @addtogroup bslstl_function_invokerutil
149 * @{
150 */
151
152#include <bslscm_version.h>
153
155
157#include <bslmf_conditional.h>
158#include <bslmf_forwardingtype.h>
160#include <bslmf_invokeresult.h>
162#include <bslmf_isvoid.h>
164#include <bslmf_movableref.h>
165
167#include <bsls_keyword.h>
168#include <bsls_libraryfeatures.h>
169#include <bsls_nullptr.h>
170
171#include <bslstl_function_rep.h>
173
174#include <utility>
175
176#if BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
177// Include version that can be compiled with C++03
178// Generated on Thu Oct 21 10:11:37 2021
179// Command line: sim_cpp11_features.pl bslstl_function_invokerutil.h
180# define COMPILING_BSLSTL_FUNCTION_INVOKERUTIL_H
182# undef COMPILING_BSLSTL_FUNCTION_INVOKERUTIL_H
183#else
184
185#ifndef BSLS_PLATFORM_CMP_SUN
186#define BSLSTL_FUNCTION_INVOKERUTIL_CAST_RESULT(RET, X) static_cast<RET>(X)
187#else
188#define BSLSTL_FUNCTION_INVOKERUTIL_CAST_RESULT(RET, X) (RET)(X)
189#endif
190
191#if defined(BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS) \
192 && defined(BSLS_COMPILERFEATURES_SUPPORT_DECLTYPE) \
193 && defined(BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES) \
194 && defined(BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY)
195#define BSLSTL_FUNCTION_INVOKERUTIL_SUPPORT_IS_FUNC_INVOCABLE
196#endif
197
198
199namespace bslstl {
200
201#ifdef BSLSTL_FUNCTION_INVOKERUTIL_SUPPORT_IS_FUNC_INVOCABLE
202
203/// forward declaration
204template <class PROTOTYPE, class FUNC>
205struct Function_InvokerUtil_IsFuncInvocable;
206
207#endif
208
209 // ===========================
210 // struct Function_InvokerUtil
211 // ===========================
212
213/// This struct is a namespace containing a single function template,
214/// `invokerForFunc`, that returns a pointer to a function that is used to
215/// invoke a callable object of a particular type.
217
218 // TYPES
219 enum {
220 // Enumeration of the different types of callable objects.
221
228 };
229
230 /// Generic function pointer. This type is as close as we can get to
231 /// `void *` for function pointers.
233
234#ifdef BSLSTL_FUNCTION_INVOKERUTIL_SUPPORT_IS_FUNC_INVOCABLE
235 /// This `struct` template implements a Boolean metafunction that
236 /// publicly inherits from `bsl::true_type` if an object of the
237 /// specified `FUNC` type is invocable under the specified `PROTOTYPE`,
238 /// and publicly inherits from `bsl::false_type` otherwise. An object
239 /// of `FUNC` type is invocable under the `PROTOTYPE` if it is
240 /// Lvalue-Callable with the arguments of the `PROTOTYPE` (as forwarded
241 /// by the facilities of 'bslmf_forwardingtype), and returns an object
242 /// of type explicitly convertible to the return type of the
243 /// `PROTOTYPE`. If the return type of the `PROTOTYPE` is `void`, then
244 /// any type is considered explicitly convertible to the return type of
245 /// the `PROTOTYPE`. This `struct` template requires 'PROTOTYPE" to be
246 /// an unqualified function type.
247 ///
248 /// Note that `IsFuncInvocable` is qualitatively different than
249 /// `std::is_invocable_r`, in that it makes concessions for supporting
250 /// legacy behavior of `bsl::function`.
251 /// `std::is_invocable_r<RET, FUNC, ARGS...>` requires that the return
252 /// type of the invocation of `FUNC` with `ARGS...` be implicitly
253 /// convertible to `RET`, as opposed to explicitly convertible.
254 /// Further, the use of `bslmf::ForwardingType` to forward arguments in
255 /// the invoker of a `bsl::function` creates qualitatively different
256 /// behavior than the argument forwarding mechanism used by the standard
257 /// `INVOKE` pseudo-expression.
258 template <class PROTOTYPE, class FUNC>
259 struct IsFuncInvocable
260 : Function_InvokerUtil_IsFuncInvocable<PROTOTYPE, FUNC> {
261 };
262#endif
263
264 // CLASS METHODS
265
266 /// Return a null pointer. Note that template argument `PROTOTYPE` must
267 /// be supplied excplicitly, as there is no way to deduce it from the
268 /// function arguments.
269 template <class PROTOTYPE>
271
272 /// Return a pointer to the invoker for a callable object of (template
273 /// paramter) type `FUNC`. If the specified `f` object is a null
274 /// pointer or null pointer-to-member, return a null pointer. Note that
275 /// template argument `PROTOTYPE` must be supplied excplicitly, as there
276 /// is no way to deduce it from the function arguments.
277 template <class PROTOTYPE, class FUNC>
278 static GenericInvoker *invokerForFunc(const FUNC& f);
279};
280
281 // =============================================
282 // template struct Function_InvokerUtilNullCheck
283 // =============================================
284
285/// Provides an `isNull` static method that that returns whether or not its
286/// argument is "null", i.e., it cannot be invoked. For must `FUNC` types
287/// `isNull` always returns `false` as every instance of `FUNC` is
288/// invocable. However, specializations of this class, especially for
289/// pointer types, have `isNull` functions that sometimes return `true`.
290/// This class is a customization point: types outside of this component can
291/// (but rarely should) specialize this template. In particular,
292/// @ref bslstl_function contains a specialization for `bsl::function`.
293template <class FUNC>
295
296 // CLASS METHODS
297
298 /// Return `false`.
299 static bool isNull(const FUNC&);
300};
301
302/// Specialization of dispatcher for pointer objects.
303template <class FUNC>
305
306 // CLASS METHODS
307
308 /// Return `true` if the specified `f` pointer is null; otherwise
309 /// `false`.
310 static bool isNull(FUNC *f);
311};
312
313/// Specialization of dispatcher for pointer-to-member objects.
314template <class CLASS, class MEMTYPE>
315struct Function_InvokerUtilNullCheck<MEMTYPE CLASS::*> {
316
317 public:
318 // CLASS METHODS
319
320 /// Return `true` if the specified `f` pointer to member is null;
321 /// otherwise `false`.
322 static bool isNull(MEMTYPE CLASS::* f);
323};
324
325#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES // $var-args=13
326
327 // ====================================================
328 // template struct Function_InvokerUtil_IsFuncInvocable
329 // ====================================================
330
331#ifdef BSLSTL_FUNCTION_INVOKERUTIL_SUPPORT_IS_FUNC_INVOCABLE
332
333/// forward declaration
334template <class VOID_TYPE, class RET, class FUNC, class... ARGS>
335struct Function_InvokerUtil_IsFuncInvocableImp;
336
337/// This `struct` template implements a Boolean metafunction that publicly
338/// inherits from `bsl::true_type` if an object of the specified `FUNC` type
339/// is invocable with the specified `RET` and `ARGS...`, and publicly
340/// inherits from `bsl::false_type` otherwise. An object of `FUNC` type is
341/// invocable with `RET` and `ARGS...` if it is Lvalue-Callable with
342/// arguments having the types of the `ARGS...`, and returns an object of
343/// type explicitly convertible to `RET`. If `RET` is `void`, then any type
344/// is considered explicitly convertible to `RET`.
345template <class RET, class FUNC, class... ARGS>
346struct Function_InvokerUtil_IsFuncInvocable<RET(ARGS...), FUNC>
347: Function_InvokerUtil_IsFuncInvocableImp<void, RET, FUNC, ARGS...> {
348};
349
350 // =======================================================
351 // template struct Function_InvokerUtil_IsFuncInvocableImp
352 // =======================================================
353
354/// forward declaration
355template <class ARG>
356struct Function_InvokerUtil_ForwardType;
357
358/// forward declaration
359template <class FROM, class TO>
360struct Function_InvokerUtil_IsExplicitlyConvertible;
361
362/// forward declaration
363template <class FUNC, class... ARGS>
364struct Function_InvokerUtil_ResultType;
365
366/// This component-private `struct` template provides the primary template
367/// definition for the `Function_InvokerUtil_IsFuncInvocableImp` Boolean
368/// metafunction, which is an implementation detail of the
369/// `Function_InvokerUtil_IsFuncInvocable` Boolean metafunction. This
370/// specialization is instantiated when `std::invoke_result<T, FWD_ARGS...>`
371/// does not provide a nested `type` typedef, where `T` is the result of
372/// stripping a nothrow-movable wrapper from `FUNC`, if present, and adding
373/// an lvalue reference, and where `FWD_ARGS...` are the types that result
374/// from forwarding objects of respective `ARGS...` types. This `struct`
375/// template requires that the specified `VOID_TYPE` type to be `void`.
376template <class VOID_TYPE, class RET, class FUNC, class... ARGS>
377struct Function_InvokerUtil_IsFuncInvocableImp : bsl::false_type {
378};
379
380/// This component-private `struct` template provides a partial
381/// specialization of `Function_InvokerUtil_IsFuncInvocableImp` for `FUNC`
382/// types for which `bsl::invoke_result<T, FWD_ARGS...>` provides a nested
383/// `type` typedef, where `T` is the result of stripping a nothrow-movable
384/// wrapper from `FUNC`, if present, and adding an lvalue reference, and
385/// where `FWD_ARGS...` are the types that result from forwarding objects
386/// of respective `ARGS...` types.
387///
388/// Specifically, `T` is
389/// `bslalg::NothrowMovableUtil::UnwrappedType<FUNC>::type&`, and
390/// `FWD_ARGS...` are the types of respective
391/// `bslmf::ForwardingTypeUtil<ARGS...>::forwardToTarget(args...)`
392/// expressions where `args...` are lvalue expressions of respective
393/// `bslmf::ForwardingType<ARGS>::Type...` types. See the class-level
394/// documentation of the primary `Function_InvokerUtil::IsFuncInvocable`
395/// declaration for more information about the behavior of this `struct`
396/// template.
397template <class RET, class FUNC, class... ARGS>
398struct Function_InvokerUtil_IsFuncInvocableImp<
399 typename bslmf::VoidType<
400 typename Function_InvokerUtil_ResultType<FUNC, ARGS...>::type>::type,
401 RET,
402 FUNC,
403 ARGS...>
405 bsl::is_void<RET>::value,
406 bsl::true_type,
407 Function_InvokerUtil_IsExplicitlyConvertible<
408 typename Function_InvokerUtil_ResultType<FUNC, ARGS...>::type,
409 RET> >::type {
410};
411
412 // ===============================================
413 // template struct Function_InvokerUtil_ResultType
414 // ===============================================
415
416/// forward declaration
417template <class VOID_TYPE, class FUNC, class... ARGS>
418struct Function_InvokerUtil_ResultTypeImp;
419
420/// This component-private `struct` template provides a metafunction that
421/// conditionally defines a nested `type` typedef if the standard
422/// `INVOKE(f, fwdArgs...)` pseudo-expression is well-formed, where `f` is
423/// an lvalue of `bslalg::NothrowMoveableUtil::UnwrappedType<FUNC>` type,
424/// and `fwdArgs...` are defined to be the expressions
425/// `bslmf::ForwardingTypeUtil<ARGS>::forwardToTarget(args)...` where
426/// `args...` are lvalue expressions of the corresponding
427/// `bslmf::ForwardingType<ARGS>::Type...` types. If such an `INVOKE`
428/// expression is well-formed, this struct defines `type` to be the result
429/// type of the expression, and defines no such typedef otherwise.
430template <class FUNC, class... ARGS>
431struct Function_InvokerUtil_ResultType
432: Function_InvokerUtil_ResultTypeImp<void, FUNC, ARGS...> {
433};
434
435 // ==================================================
436 // template struct Function_InvokerUtil_ResultTypeImp
437 // ==================================================
438
439/// This component-private `struct` template provides the primary template
440/// definition for the `Function_InvokerUtil_ResultTypeImp` metafunction,
441/// which is an implementation detail of the
442/// `Function_InvokerUtil_ResultType` metafunction. This specialization is
443/// instantiated when the standard `INVOKE(f, fwdArgs...)` pseudo-expression
444/// is not well-formed, where `f` is an lvalue of
445/// `bslalg::NothrowMoveableUtil::UnwrappedType<FUNC>` type, and
446/// `fwdArgs...` are defined to be the expressions
447/// `bslmf::ForwardingTypeUtil<ARGS>::forwardToTarget(args)...` where
448/// `args...` are lvalue expressions of the corresponding
449/// `bslmf::ForwardingType<ARGS>::Type...` types.
450template <class VOID_TYPE, class FUNC, class... ARGS>
451struct Function_InvokerUtil_ResultTypeImp {
452};
453
454template <class FUNC, class... ARGS>
455struct Function_InvokerUtil_ResultTypeImp<
456 typename bslmf::VoidType<
457 typename Function_InvokerUtil_ForwardType<ARGS>::Type...>::type,
458 FUNC,
459 ARGS...>
461 typename bsl::add_lvalue_reference<typename bslalg::NothrowMovableUtil::
462 UnwrappedType<FUNC>::type>::type,
463 typename Function_InvokerUtil_ForwardType<ARGS>::Type...> {
464
465 // This component-private 'struct' template provides a partial
466 // specialization of 'Function_InvokerUtil_ResultTypeImp' for 'FUNC' and
467 // 'ARGS...' types for which standard 'INVOKE(f, fwdArgs...)'
468 // pseudo-expression is well-formed, where 'f' is an lvalue of
469 // 'bslalg::NothrowMoveableUtil::UnwrappedType<FUNC>' type, and
470 // 'fwdArgs...' are defined to be the expressions
471 // 'bslmf::ForwardingTypeUtil<ARGS>::forwardToTarget(args)...' where
472 // 'args...' are lvalue expressions of the corresponding
473 // 'bslmf::ForwardingType<ARGS>::Type...' types. This 'struct' defines a
474 // nested typedef 'type' that is the type of this expression.
475};
476
477 // ================================================
478 // template struct Function_InvokerUtil_ForwardType
479 // ================================================
480
481/// forward declaration
482template <class VOID_TYPE, class ARG>
483struct Function_InvokerUtil_ForwardTypeImp;
484
485/// This component-private `struct` template provides a metafunction that
486/// conditionally defines a nested `type` typedef that is the type resulting
487/// from forwarding an lvalue of the specified `ARG` type using the
488/// machinery from @ref bslmf_forwardingtype . If it is not possible to forward
489/// an object of `ARG` type (if, for example, `ARG` is `void`) then this
490/// `struct` template does not define a `type` typedef.
491///
492/// Specifically, `type` is defined to be the type of the expression
493/// `bslmf::ForwardingTypeUtil<ARG>::forwardingToTarget(arg)`, where `arg`
494/// is an lvalue expression of `bslmf::ForwardingType<ARG>::Type` type.
495/// `type` is not defined when this expression is not well-formed.
496template <class ARG>
497struct Function_InvokerUtil_ForwardType
498: Function_InvokerUtil_ForwardTypeImp<void, ARG> {
499};
500
501 // ===================================================
502 // template struct Function_InvokerUtil_ForwardTypeImp
503 // ===================================================
504
505/// This component-private `struct` template provides the primary template
506/// definition for the `Function_InvokerUtil_ForwardTypeImp` metafunction,
507/// which is an implementation detail of the
508/// `Function_InvokerUtil_IsFuncInvocable` metafunction. This
509/// specialization is instantiated when the expression
510/// `bslmf::ForwardingTypeUtil<ARG>::forwardToTarget(arg)` is not
511/// well-formed, where `arg` is an lvalue expression of
512/// `bslmf::ForwardingType<ARG>::Type` type.
513template <class VOID_TYPE, class ARG>
514struct Function_InvokerUtil_ForwardTypeImp {
515};
516
517/// This component-private `struct` template provides a partial
518/// specialization of `Function_InvokerUtil_ForwardTypeImp` for `ARG` types
519/// for which the expression
520/// `bslmf::ForwardingTypeUtil<ARG>::forwardToTarget(arg)` is well-formed,
521/// where `arg` is an lvalue expression of
522/// `bslmf::ForwardingType<ARG>::Type` type. This `struct` template
523/// defines a nested `type` typedef that is the type of the expression.
524/// This is the type resulting from forwarding an lvalue of the specified
525/// `ARG` type using the machinery from @ref bslmf_forwardingtype .
526template <class ARG>
527struct Function_InvokerUtil_ForwardTypeImp<
528 typename bslmf::VoidType<decltype(
529 bslmf::ForwardingTypeUtil<ARG>::forwardToTarget(
530 std::declval<typename bsl::add_lvalue_reference<
531 typename bslmf::ForwardingType<ARG>::Type>::type>()))>::type,
532 ARG> {
533
534 // TYPES
535
536 /// `Type` is an alias to the "forwarded" type of the specified `ARG`
537 /// type. Specifically, it is the type of the expression
538 /// `bslmf::ForwardingTypeUtil<ARG>::forwardingToTarget(arg)`, where
539 /// `arg` is an lvalue expression of `bslmf::ForwardingType<ARG>::Type`
540 /// type.
542 std::declval<typename bsl::add_lvalue_reference<
543 typename bslmf::ForwardingType<ARG>::Type>::type>())) Type;
544};
545
546 // ============================================================
547 // template struct Function_InvokerUtil_IsExplicitlyConvertible
548 // ============================================================
549
550/// forward declaration
551template <class VOID_TYPE, class FROM, class TO>
552struct Function_InvokerUtil_IsExplicitlyConvertibleImp;
553
554/// This component-private `struct` template provides a Boolean metafunction
555/// that publicly derives from `bsl::true_type` if the specified `FROM` type
556/// can be explicitly converted to the specified `TO` type, and derives from
557/// `bsl::false_type` otherwise. The type `FROM` is explicitly convertible
558/// to the type `TO` if the expression
559/// `static_cast<TO>(std::declval<FROM>())` is well-formed.
560template <class FROM, class TO>
561struct Function_InvokerUtil_IsExplicitlyConvertible
562: Function_InvokerUtil_IsExplicitlyConvertibleImp<void, FROM, TO> {
563};
564
565/// A type is always explicitly convertible to itself. This is important
566/// for classes with deleted copy constructors and/or assignment operators,
567/// because starting in C++17, they can be returned from functions, due to
568/// "return value optimization (RVO)".
569template <class FROM_TO>
570struct Function_InvokerUtil_IsExplicitlyConvertible<FROM_TO, FROM_TO>
572};
573
574 // ===============================================================
575 // template struct Function_InvokerUtil_IsExplicitlyConvertibleImp
576 // ===============================================================
577
578/// This component-private `struct` template provides the primary
579/// specialization of the `Function_InvokerUtil_IsExplicitlyConvertibleImp`
580/// metafunction. This specialization is instantiated when the specified
581/// `FROM` type is not explicitly convertible to the specified `TO` type,
582/// and publicly ihherits from `bsl::false_type`. This `struct` template
583/// requires the specified `VOID_TYPE` type to be `void`.
584template <class VOID_TYPE, class FROM, class TO>
585struct Function_InvokerUtil_IsExplicitlyConvertibleImp : bsl::false_type {
586};
587
588/// This component-private `struct` template provides a partial
589/// specialization of the `Function_InvokerUtil_IsExplicitlyConvertibleImp`
590/// metafunction. This specialization is instantiated when the specified
591/// `FROM` type is explicitly convertible to the specified `TO` type, and
592/// publicly inherits from `bsl::true_type`.
593template <class FROM, class TO>
594struct Function_InvokerUtil_IsExplicitlyConvertibleImp<
595 typename bslmf::VoidType<decltype(
596 static_cast<TO>(std::declval<FROM>()))>::type,
597 FROM,
598 TO> : bsl::true_type {
599};
600
601#endif // defined(BSLSTL_FUNCTION_INVOKERUTIL_SUPPORT_IS_FUNC_INVOCABLE)
602#endif
603
604 // =============================================
605 // template struct Function_InvokerUtil_Dispatch
606 // =============================================
607
608/// Specializations of this class contain a static `invoke` method that can
609/// invoke a callable object of type `FUNC`, converting each argument in
610/// `PROTOTYPE` (a function prototype) to the corresponding argument in the
611/// invocation of the callable object and converting the return value of the
612/// invocation to the return type of `PROTOTYPE`. The `INVOCATION_TYPE`
613/// specifies the category of callable object: pointer to function, pointer
614/// to member function, pointer to data member, inplace functor (i.e., one
615/// that qualifies for the small-object optimization) and out-of-place
616/// functor (i.e., one that is not stored in the small-object buffer).
617template <int INVOCATION_TYPE, class PROTOTYPE, class FUNC>
619
620#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES // $var-args=13
621
622// STATIC METHODS OF PRIVATE NESTED *Invoker CLASS TEMPLATES
623
624/// Specialization of dispatcher for pointer-to-function objects.
625template <class FUNC, class RET, class... ARGS>
627 RET(ARGS...), FUNC> {
628
629 // CLASS METHODS
630
631 /// For the specified `rep` and `args`, return
632 /// `rep.target<FUNC>()(args...)`.
633 static RET invoke(const Function_Rep *rep,
634 typename bslmf::ForwardingType<ARGS>::Type... args);
635};
636
637/// Specialization of dispatcher for pointer to member function objects.
638template <class FUNC, class RET, class ARG0, class... ARGS>
640 RET(ARG0, ARGS...), FUNC> {
641
642 private:
643 // PRIVATE CLASS METHODS
644
645 /// Use the specified `obj` to invoke the specified `f` pointer to
646 /// member function with the specified `args` and return the result,
647 /// i.e., `(obj.*f)(args...)`.
648 static RET invokeImp(bsl::true_type /* isDirect */,
649 FUNC f,
651 typename bslmf::ForwardingType<ARGS>::Type... args);
652
653 /// Dereference the specified `obj` and usit to invoke the specified `f`
654 /// pointer to member function with the specified `args` and return the
655 /// result, i.e., `((*obj).*f)(args...)`.
656 static RET invokeImp(bsl::false_type /* isDirect */,
657 FUNC f,
659 typename bslmf::ForwardingType<ARGS>::Type... args);
660
661 public:
662 // CLASS METHODS
663
664 /// Given pointer to member function, `f`, as the target of the
665 /// specified `rep`, use the specified `obj` to invoke `f` with the
666 /// specified `args` and return the result, i.e., `(obj.*f)(args...)`.
667 /// If `obj` is a pointer or smart-pointer, dereference `obj` first,
668 /// i.e., call `((*obj).*f)(args...)`.
669 static RET invoke(const Function_Rep *rep,
671 typename bslmf::ForwardingType<ARGS>::Type... args);
672};
673
674/// Specialization of dispatcher for pointer to data member objects.
675template <class MEMBER_TYPE, class CLASS_TYPE, class RET, class ARG0>
677 RET(ARG0), MEMBER_TYPE CLASS_TYPE::*> {
678 private:
679 // PRIVATE CLASS METHODS
680 typedef MEMBER_TYPE CLASS_TYPE::* Func;
681
682 /// Return the specified `f` member of the specified `obj`, i.e.,
683 /// `obj.*f`.
684 static RET invokeImp(bsl::true_type /* isDirect */,
685 Func f,
687
688 /// Return the specified `f` member of the object obtained by
689 /// dereferencing the specified `obj`, i.e., `(*obj).f`.
690 static RET invokeImp(bsl::false_type /* isDirect */,
691 Func f,
693
694 public:
695 // CLASS METHODS
696
697 /// Given pointer to data member, `f`, as the target of the specified
698 /// `rep`, return the specified `f` member of the specified `obj`, i.e.,
699 /// `obj.*f`. If `obj` is a pointer or smart-pointer, dereference `obj`
700 /// first, i.e., return `(*obj).*f`.
701 static RET invoke(const Function_Rep *rep,
703};
704
705/// Specialization of dispatcher functor class objects that are suitable for
706/// the small-object optimization and are thus allocated inplace.
707template <class FUNC, class RET, class... ARGS>
709 RET(ARGS...), FUNC> {
710
711 // CLASS METHODS
712
713 /// For the specified `args` and `rep`, return
714 /// `(*rep.target<FUNC>())(args...)`.
715 static RET invoke(const Function_Rep *rep,
716 typename bslmf::ForwardingType<ARGS>::Type... args);
717};
718
719/// Specialization of dispatcher functor class objects that are not suitable
720/// for the small-object optimization and are thus allocated out of place.
721template <class FUNC, class RET, class... ARGS>
723 RET(ARGS...), FUNC> {
724
725 // CLASS METHODS
726
727 /// For the specified `args` and `rep`, return
728 /// `(*rep.target<FUNC>())(args...)`.
729 static RET invoke(const Function_Rep *rep,
730 typename bslmf::ForwardingType<ARGS>::Type... args);
731};
732
733#endif
734
735// ===========================================================================
736// TEMPLATE AND INLINE FUNCTION IMPLEMENTATIONS
737// ===========================================================================
738
739 // ---------------------------
740 // struct Function_InvokerUtil
741 // ---------------------------
742
743template <class PROTOTYPE>
744inline
750
751template <class PROTOTYPE, class FUNC>
754{
756
757 // Strip 'NothrowMovableWrapper' (if any) off of 'FUNC' type.
758 typedef typename
760
761 // Categorize the type of invocable corresponding to 'FUNC'. Note that the
762 // parameter to 'Soo::Inplace' is 'FUNC', not 'UwFuncType'. That is
763 // because 'Soo::Inplace' takes the wrapper into account when determining
764 // whether the type should be inplace or not.
765 static const int k_INVOCATION_TYPE =
769 Soo::IsInplaceFunc<FUNC>::value ? e_InplaceFunctor :
770 e_OutofplaceFunctor;
771
772 // Instantiate the class for checking for null object
773 typedef Function_InvokerUtilNullCheck<UwFuncType> NullCheckerClass;
774
775 // Instantiate the class for dispatching the invoker
776 typedef Function_InvokerUtil_Dispatch<k_INVOCATION_TYPE,
777 PROTOTYPE,
778 UwFuncType> DispatcherClass;
779
780 // If a the object is "null", e.g., for a pointer, then return null.
781 if (NullCheckerClass::isNull(bslalg::NothrowMovableUtil::unwrap(f)))
782 {
783 return 0; // RETURN
784 }
785
786 // Verify the assumption that all function pointers are the same size.
787 BSLMF_ASSERT(sizeof(&DispatcherClass::invoke) ==
789
790 // Return a pointer to the actual invoker function
791 return reinterpret_cast<Function_Rep::GenericInvoker *>(
792 &DispatcherClass::invoke);
793}
794
795 // ---------------------------------------------
796 // struct template Function_InvokerUtilNullCheck
797 // ---------------------------------------------
798
799// STATIC MEMBER FUNCTIONS
800
801template <class FUNC>
802inline
804{
805 return false;
806}
807
808template <class FUNC>
809inline
811{
812 return 0 == f;
813}
814
815template <class CLASS, class MEMTYPE>
816inline
817bool
819{
820 return 0 == f;
821}
822
823
824 // ---------------------------------------------
825 // struct template Function_InvokerUtil_Dispatch
826 // ---------------------------------------------
827
828#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
829
830template <class FUNC, class RET, class... ARGS>
831RET
832Function_InvokerUtil_Dispatch<Function_InvokerUtil::e_FunctionPtr,
833 RET(ARGS...), FUNC>::
834invoke(const Function_Rep *rep,
835 typename bslmf::ForwardingType<ARGS>::Type... args)
836{
837 FUNC f = *rep->targetRaw<FUNC, true>();
838
839 // Note that 'FUNC' might be different than 'RET(*)(ARGS...)'. All that is
840 // required is that it be Callable with 'ARGS...' and return something
841 // convertible to 'RET'.
842
843 // Cast to 'RET' is needed to avoid compilation error if 'RET' is 'void'
844 // and 'f' returns non-void.
846 RET,
848}
849
850template <class FUNC, class RET, class ARG0, class... ARGS>
851inline
852RET
854 RET(ARG0, ARGS...), FUNC>::
855invokeImp(bsl::true_type /* isDirect */,
856 FUNC f,
858 typename bslmf::ForwardingType<ARGS>::Type... args)
859{
860 typedef typename
862
863 // In C++03, an rvalue is forwarded as a const lvalue. Fortunately, we can
864 // recover the correct constness by casting 'obj' back to a reference to
865 // the original type.
867 RET, (const_cast<Arg0Ref>(obj).*f)(
869}
870
871template <class FUNC, class RET, class ARG0, class... ARGS>
872inline
873RET
874Function_InvokerUtil_Dispatch<Function_InvokerUtil::e_MemFunctionPtr,
875 RET(ARG0, ARGS...), FUNC>::
876invokeImp(bsl::false_type /* isDirect */,
877 FUNC f,
879 typename bslmf::ForwardingType<ARGS>::Type... args)
880{
881 typedef typename
883
884 // In C++03, an rvalue is forwarded as a const lvalue. Fortunately, we can
885 // recover the correct constness from by casting back to a reference to
886 // the original type.
888 RET, ((*const_cast<Arg0Ref>(obj)).*f)(
890}
891
892template <class FUNC, class RET, class ARG0, class... ARGS>
893RET
894Function_InvokerUtil_Dispatch<Function_InvokerUtil::e_MemFunctionPtr,
895 RET(ARG0, ARGS...), FUNC>::
896invoke(const Function_Rep *rep,
898 typename bslmf::ForwardingType<ARGS>::Type... args)
899{
900 typedef typename
902
903 /// `true_type` if `ARG0` is a reference to `ClassType` or class derived
904 /// from `ClassType; otherwise, `false_type'.
905 typedef typename bsl::is_convertible<
907 ClassType *
908 >::type IsDirect;
909
910 FUNC f = *rep->targetRaw<FUNC, true>();
911
913 invokeImp(IsDirect(), f, obj,
914 args...));
915}
916
917template <class MEMBER_TYPE, class CLASS_TYPE, class RET, class ARG0>
918inline
919RET
921 RET(ARG0), MEMBER_TYPE CLASS_TYPE::*>::
922invokeImp(bsl::true_type /* isDirect */,
923 Func f,
925{
926 typedef typename
928
929 // In C++03, an rvalue is forwarded as a const lvalue. Fortunately, we can
930 // recover the correct constness by casting 'obj' back to a reference to
931 // the original type.
933 RET, (const_cast<Arg0Ref>(obj).*f));
934}
935
936template <class MEMBER_TYPE, class CLASS_TYPE, class RET, class ARG0>
937inline
938RET
939Function_InvokerUtil_Dispatch<Function_InvokerUtil::e_MemDataPtr,
940 RET(ARG0), MEMBER_TYPE CLASS_TYPE::*>::
941invokeImp(bsl::false_type /* isDirect */,
942 Func f,
944{
945 typedef typename
947
948 // In C++03, an rvalue is forwarded as a const lvalue. Fortunately, we can
949 // recover the correct constness from by casting back to a reference to
950 // the original type.
952 RET, ((*const_cast<Arg0Ref>(obj)).*f));
953}
954
955template <class MEMBER_TYPE, class CLASS_TYPE, class RET, class ARG0>
956RET
957Function_InvokerUtil_Dispatch<Function_InvokerUtil::e_MemDataPtr,
958 RET(ARG0), MEMBER_TYPE CLASS_TYPE::*>::
959invoke(const Function_Rep *rep,
961{
962 /// `true_type` if `ARG0` is a reference to `CLASS_TYPE` or class
963 /// derived from `CLASS_TYPE; otherwise, `false_type'. Note that this
964 /// differs from the corresponding check for pointers to member
965 /// functions because a pointer to data member for class type `T` can
966 /// be used to access (as const) a member of a cv-qualified `T`.
967 typedef typename bsl::is_convertible<
969 const volatile CLASS_TYPE *
970 >::type IsDirect;
971
972 Func f = *rep->targetRaw<Func, true>();
973
975 RET, invokeImp(IsDirect(), f, obj));
976}
977
978template <class FUNC, class RET, class... ARGS>
979RET
980Function_InvokerUtil_Dispatch<Function_InvokerUtil::e_InplaceFunctor,
981 RET(ARGS...), FUNC>::
982invoke(const Function_Rep *rep,
983 typename bslmf::ForwardingType<ARGS>::Type... args)
984{
985 FUNC& f = *rep->targetRaw<FUNC, true>();
986
987 // Cast to 'RET' is needed to avoid compilation error if 'RET' is void and
988 // 'f' returns non-void.
990 RET,
992}
993
994template <class FUNC, class RET, class... ARGS>
995RET
997 RET(ARGS...), FUNC>::
998invoke(const Function_Rep *rep,
999 typename bslmf::ForwardingType<ARGS>::Type... args)
1000{
1001 FUNC& f = *rep->targetRaw<FUNC, false>();
1002
1003 // Cast to 'RET' is needed to avoid compilation error if 'RET' is void and
1004 // 'f' returns non-void.
1006 RET,
1008}
1009
1010#endif
1011
1012} // close package namespace
1013
1014
1015#endif // End C++11 code
1016
1017#endif // ! defined(INCLUDED_BSLSTL_FUNCTION_INVOKERUTIL)
1018
1019// ----------------------------------------------------------------------------
1020// Copyright 2020 Bloomberg Finance L.P.
1021//
1022// Licensed under the Apache License, Version 2.0 (the "License");
1023// you may not use this file except in compliance with the License.
1024// You may obtain a copy of the License at
1025//
1026// http://www.apache.org/licenses/LICENSE-2.0
1027//
1028// Unless required by applicable law or agreed to in writing, software
1029// distributed under the License is distributed on an "AS IS" BASIS,
1030// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1031// See the License for the specific language governing permissions and
1032// limitations under the License.
1033// ----------------------------- END-OF-FILE ----------------------------------
1034
1035/** @} */
1036/** @} */
1037/** @} */
Definition bslmf_invokeresult.h:358
Provide a namespace for the forwardToTarget function.
Definition bslmf_forwardingtype.h:454
Imp::Type Type
Definition bslmf_forwardingtype.h:439
Definition bslstl_function_rep.h:132
void GenericInvoker()
Definition bslstl_function_rep.h:369
Definition bslstl_function_smallobjectoptimization.h:78
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:229
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLSTL_FUNCTION_INVOKERUTIL_CAST_RESULT(RET, X)
Definition bslstl_function_invokerutil.h:186
TP * targetRaw() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_function_rep.h:725
BloombergLP::bsls::Nullptr_Impl::Type nullptr_t
Definition bsls_nullptr.h:281
Definition bdlbb_blob.h:576
Definition bslstl_algorithm.h:82
Definition bslmf_addlvaluereference.h:126
Definition bslmf_conditional.h:120
Definition bslmf_integralconstant.h:244
Definition bslmf_isconvertible.h:867
Definition bslmf_ismemberpointer.h:143
NothrowMovableUtil_Traits< TYPE >::UnwrappedType type
Definition bslalg_nothrowmovableutil.h:370
static UnwrappedType< TYPE >::type & unwrap(TYPE &f)
Definition bslmf_functionpointertraits.h:153
Definition bslmf_memberfunctionpointertraits.h:164
Definition bslmf_memberfunctionpointertraits.h:150
t_TYPE type
Definition bslmf_movableref.h:1177
Definition bslstl_function_invokerutil.h:294
static bool isNull(const FUNC &)
Return false.
Definition bslstl_function_invokerutil.h:803
static RET invoke(const Function_Rep *rep, typename bslmf::ForwardingType< ARG0 >::Type obj)
Definition bslstl_function_invokerutil.h:618
Definition bslstl_function_invokerutil.h:216
@ e_Null
Definition bslstl_function_invokerutil.h:222
@ e_MemDataPtr
Definition bslstl_function_invokerutil.h:225
@ e_FunctionPtr
Definition bslstl_function_invokerutil.h:223
@ e_InplaceFunctor
Definition bslstl_function_invokerutil.h:226
@ e_OutofplaceFunctor
Definition bslstl_function_invokerutil.h:227
@ e_MemFunctionPtr
Definition bslstl_function_invokerutil.h:224
static GenericInvoker * invokerForFunc(const bsl::nullptr_t &)
Function_Rep::GenericInvoker GenericInvoker
Definition bslstl_function_invokerutil.h:232
static GenericInvoker * invokerForFunc(const FUNC &f)