BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslmf_invokeresult.h
Go to the documentation of this file.
1/// @file bslmf_invokeresult.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslmf_invokeresult.h -*-C++-*-
8#ifndef INCLUDED_BSLMF_INVOKERESULT
9#define INCLUDED_BSLMF_INVOKERESULT
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslmf_invokeresult bslmf_invokeresult
15/// @brief Determine the result type of an invocable expression.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslmf
19/// @{
20/// @addtogroup bslmf_invokeresult
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslmf_invokeresult-purpose"> Purpose</a>
25/// * <a href="#bslmf_invokeresult-classes"> Classes </a>
26/// * <a href="#bslmf_invokeresult-macros"> Macros </a>
27/// * <a href="#bslmf_invokeresult-description"> Description </a>
28/// * <a href="#bslmf_invokeresult-c-17-semantics-detection"> C++17 Semantics Detection </a>
29/// * <a href="#bslmf_invokeresult-precise-specification"> Precise specification </a>
30/// * <a href="#bslmf_invokeresult-usage-example"> Usage Example </a>
31///
32/// # Purpose {#bslmf_invokeresult-purpose}
33/// Determine the result type of an invocable expression.
34///
35/// # Classes {#bslmf_invokeresult-classes}
36///
37/// - bsl::invoke_result: Metafunction to determine invocation result type
38/// - bsl::invoke_result_t: alias to the return type of the `bsl::invoke_result`
39/// - bslmf::InvokeResultDeductionFailed: Returned on failed result deduction
40///
41/// # Macros {#bslmf_invokeresult-macros}
42///
43/// - BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS: defined if SFINAE-friendly
44///
45/// @see bslstl_invoke
46///
47/// # Description {#bslmf_invokeresult-description}
48/// This component provides a metafunction `bsl::invoke_result`
49/// that determines, at compile time, the type returned by invoking a callable
50/// type, including pointer-to-function, pointer-to-member function,
51/// pointer-to-member object (returns the object type), or functor class and a
52/// class `bslmf::InvokeResultDeductionFailed` that is returned when the
53/// invocation return type cannot be determined (C++03 only). For a set of
54/// types `F`, `T1`, `T2`, and `T3`, `bsl::invoke_result<F, T1, t2, T3>::type`
55/// is roughly the type of the return value obtained by calling an object of
56/// type `F` with arguments of type `T1`, `T2`, and `T3`, respectively.
57/// However, @ref invoke_result goes beyond function-like objects and deduces a
58/// return type if `F` is a pointer to function member or data member of some
59/// class `C` and `T1` is a type (derived from) `C`, pointer to `C`, or
60/// smart-pointer to `C`. (See precise specification, below). For the
61/// convenience of users, an alias for the type returned by the
62/// `bsl::invoke_result`, `bsl::invoke_result_t`, is provided by this component.
63///
64/// The interfaces and functionality of `bsl::invoke_result` and
65/// `bsl::invoke_result_t` are intended to be identical to that of the C++17
66/// metafunctions, `std::invoke_result` and `std::invoke_result_t` except that
67/// invalid argument lists are detected in C++11 and later, but not in C++03.
68/// In C++03, invalid arguments lists will result in a compilation error
69/// (instead of simply missing `type`) in the remaining cases. Some other
70/// functionality is lost when compiling with a C++03 compiler -- see the
71/// precise specification, below.
72///
73/// ## C++17 Semantics Detection {#bslmf_invokeresult-c-17-semantics-detection}
74///
75///
76/// This component defines the macro
77/// `BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS` if `bsl::invoke_result` behaves
78/// according to the C++17 specification of `std::invoke_result`, which is
79/// elaborated below. This macro is defined as long as the compiler supports
80/// the `decltype` specifier, which is generally available in C++11 and later
81/// compilation modes.
82///
83/// ## Precise specification {#bslmf_invokeresult-precise-specification}
84///
85///
86/// The C++11 and C++14 standard defines the pseudo-expression
87/// <u>INVOKE</u> `(f, t1, t2, ..., tN)`, as follows:
88///
89/// * `(t1.*f)(t2, ..., tN)` when `f` is a pointer to a member function of a
90/// class `T` and `t1` is an object of type `T` or a reference to an object
91/// of type `T` or a reference to an object of a type derived from `T`;
92/// * `((*t1).*f)(t2, ..., tN)` when `f` is a pointer to a member function of
93/// a class `T` and `t1` is not one of the types described in the previous
94/// item;
95/// * `t1.*f` when `N == 1` and `f` is a pointer to member data of a class `T`
96/// and `t1` is an object of type `T` or a reference to an object of type
97/// `T` or a reference to an object of a type derived from `T`;
98/// * `(*t1).*f` when `N == 1` and `f` is a pointer to member data of a class
99/// `T` and `t1` is not one of the types described in the previous item;
100/// * `f(t1, t2, ..., tN)` in all other cases.
101///
102/// Given types `F`, `T1`, `T2`, ..., `TN` corresponding to the expressions
103/// `f`, `t1`, `t2`, ..., `tN` in the definition of <u>INVOKE</u>, the type produced
104/// by `bslmf::ResultType<F, T1, T2, ..., TN>::type` is generally the type of
105/// the psuedo-expression <u>INVOKE</u> `(f, t1, t2, ..., tN)`, with some
106/// limitations in C++03, as described below.
107///
108/// Because C++03 does not support `decltype`, there are circumstances in which
109/// `bsl::invoke_result` is not able to deduce the return type of an invocable
110/// object of class type (i.e., a functor). If `R` is the type of the <u>INVOKE</u>
111/// expression, then ideally `type` is `R`. However the C++03 version of
112/// `bsl::invoke_result` determines `type` as follows:
113///
114/// 1. If there exists a user-defined specialization of
115/// `bsl::invoke_result<F, T1, T2, ... TN>`, then `type` is determined by the
116/// specialization, regardless of correctness. (This rule is true of C++11
117/// and later, as well.)
118/// 2. Otherwise, if `F` is a function type, pointer to function type, pointer
119/// to member function type, pointer to member object type, or reference to
120/// any of these (i.e, `F` is anything other than a class type or reference
121/// to class type), then `type` is `R`.
122/// 3. Otherwise, if `R` is o a fundamental type, o a pointer to (possibly
123/// cv-qualified) `void` or fundamental type, o an lvalue reference to any of
124/// the above types (possibly cv-qualified), o `bsl::nullptr_t`, or o `void`,
125/// then `type` is `R`.
126/// 4. Otherwise, if `F` is a class type with member `result_type`, then `type`
127/// is `F::result_type`. Note that `bsl::invoke_result` cannot deduce
128/// different result types for different overloads of `operator()` in this
129/// case.
130/// 5. Otherwise, if `F` is a class type with member type `ResultType`, then
131/// `type` is `F::ResultType`. Note that `bsl::invoke_result` cannot deduce
132/// different result types for different overloads of `operator()` in this
133/// case.
134/// 6. Otherwise, `type` is `bslmf::InvokeResultDeductionFailed`. The benefit
135/// of this placeholder over a compilation error is that @ref invoke_result is
136/// often used in a context where the return value will eventually be
137/// discarded. Thus, generating a useless type is often harmless. In cases
138/// where it is not harmless, the placeholder type will almost certainly
139/// result in a compilation error in the surrounding code.
140///
141/// If the callable type is a pointer-to-member (data or function), invalid
142/// argument lists are not detected. Thus, there is a small chance that invalid
143/// code will compile successfully, though it is hard to see now this would be
144/// harmful, since determining the return type of an expression is not very
145/// useful if the expression is not eventually evaluated, which will certainly
146/// produce the expected compilation error for invalid argument lists.
147///
148/// ## Usage Example {#bslmf_invokeresult-usage-example}
149///
150///
151/// Suppose we want to create a wrapper that executes an invocable object and
152/// sets a `done` flag. The `done` flag will not be set if the invocation
153/// exits via an exception. The wrapper takes an invocable `f` and an argument
154/// `x` and evaluates `f(x)`, returning the result. In the absence of C++14
155/// automatically-deduced function return declarations, we use
156/// `bsl::invoke_result` to deduce the return type of `f(x)`.
157///
158/// First, we write the wrapper template as follows:
159/// @code
160/// template <class FT, class XT>
161/// typename bsl::invoke_result<FT, XT>::type
162/// invokeAndSetFlag(bool *done, FT f, XT x)
163/// // Return 'f(x)' and set '*done' to true if no exception.
164/// {
165/// typedef typename bsl::invoke_result<FT, XT>::type ResultType;
166/// *done = false; // Clear flag in case of exception
167/// ResultType result = f(x);
168/// *done = true; // Set flag on success
169/// return result;
170/// }
171/// @endcode
172/// Note that additional metaprogramming would be required to make this
173/// template work for return type `void`; such metaprogramming is beyond the
174/// scope of this usage example.
175///
176/// Then we define a couple of simple functors to be used with the wrapper.
177/// The first functor is a simple template that triples its invocation
178/// argument:
179/// @code
180/// template <class t_TP>
181/// struct Triple {
182/// // Functor that triples its argument.
183///
184/// t_TP operator()(t_TP v) const { return static_cast<t_TP>(v * 3); }
185/// // Return three times the specified 'v' value.
186/// };
187/// @endcode
188/// Next, we define a second functor that returns an enumerator `ODD` or
189/// `EVEN`, depending on whether its argument is exactly divisible by 2. Since
190/// the return type is not a fundamental type, this functor indicates its
191/// return type using the `ResultType` idiom:
192/// @code
193/// enum EvenOdd { e_EVEN, e_ODD };
194///
195/// struct CalcEvenOdd {
196/// // Functor that determines whether its argument is odd or even.
197///
198/// typedef EvenOdd ResultType;
199///
200/// EvenOdd operator()(int i) const { return (i & 1) ? e_ODD : e_EVEN; }
201/// // Return 'e_ODD' if the specified 'i' is odd; otherwise return
202/// // 'e_EVEN'
203/// };
204/// @endcode
205/// Finally, we can invoke these functors through our wrapper:
206/// @code
207/// int main()
208/// // Run the usage example.
209/// {
210/// bool done = false;
211///
212/// Triple<short> ts = {};
213/// short r0 = invokeAndSetFlag(&done, ts, short(9));
214/// assert(done && 27 == r0);
215///
216/// CalcEvenOdd ceo = {};
217/// done = false;
218/// EvenOdd r1 = invokeAndSetFlag(&done, ceo, 5);
219/// assert(done && e_ODD == r1);
220///
221/// done = false;
222/// EvenOdd r2 = invokeAndSetFlag(&done, ceo, 8);
223/// assert(done && e_EVEN == r2);
224///
225/// return 0;
226/// }
227/// @endcode
228/// @}
229/** @} */
230/** @} */
231
232/** @addtogroup bsl
233 * @{
234 */
235/** @addtogroup bslmf
236 * @{
237 */
238/** @addtogroup bslmf_invokeresult
239 * @{
240 */
241
242#include <bslscm_version.h>
243
244#include <bslmf_addconst.h>
246#include <bslmf_addpointer.h>
248#include <bslmf_addvolatile.h>
249#include <bslmf_assert.h>
250#include <bslmf_decay.h>
251#include <bslmf_enableif.h>
254#include <bslmf_isclass.h>
255#include <bslmf_isconvertible.h>
258#include <bslmf_isreference.h>
261#include <bslmf_isvoid.h>
264#include <bslmf_movableref.h>
265#include <bslmf_removecv.h>
266#include <bslmf_resulttype.h>
267#include <bslmf_tag.h>
268#include <bslmf_voidtype.h>
269
271#include <bsls_nullptr.h>
272#include <bsls_platform.h>
273
274#if BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
275// Include version that can be compiled with C++03
276// Generated on Thu Feb 16 18:08:36 2023
277// Command line: sim_cpp11_features.pl bslmf_invokeresult.h
278# define COMPILING_BSLMF_INVOKERESULT_H
280# undef COMPILING_BSLMF_INVOKERESULT_H
281#else
282
283#if defined(BSLS_COMPILERFEATURES_SUPPORT_DECLTYPE) \
284 && !(defined(BSLS_PLATFORM_CMP_MSVC) && BSLS_PLATFORM_CMP_VERSION == 1800)
285// The implementation of C++17 semantics in this component depends upon the
286// use of 'decltype' for expression SFINAE. MSVC 2013 (which has version
287// number 1800) claims to support 'decltype', but does not have a sufficiently
288// functional implementation of expression sfinae to enable C++17 semantics.
289#define BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS 1
290#endif
291
292
293namespace bslmf {
294
295 // ==========================================
296 // class template InvokeResultDeductionFailed
297 // ==========================================
298
299/// When @ref invoke_result cannot deduce the actual return type of a functor
300/// (in C++03 mode), it yields this type as a placeholder. The advantage of
301/// using this placeholder instead of a compilation failure (e.g., using a
302/// static assert) is that the return type of an INVOKE() operation is
303/// often discarded, so our failure to deduce the return type is often
304/// harmless. Since `InvokeResultDeductionFailed` is a return type, it must
305/// be convertible from the actual return type; this conversion is
306/// accomplished by means of a constructor that makes it convertible from
307/// *any* type.
309
310 // CREATORS
311
312 /// Convert from an arbitrary type. The actual argument value is
313 /// discarded.
314 template <class t_TYPE>
316 {
317 }
318};
319
320#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES // $var-args=13
321
322/// Forward declaration
323template <class t_FN, class... t_ARGTYPES>
324struct InvokeResult_BaseCalcUtil;
325
326#endif
327
328} // close package namespace
329
330
331 // ============================
332 // class template invoke_result
333 // ============================
334
335namespace bsl {
336
337#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES // $var-args=13
338
339/// This class is a metafunction that conditionally provides a `type` member
340/// that is the type resulting from invoking an object of the specified
341/// `t_FN` template parameter with arguments of the specified `t_ARGTYPES`
342/// template parameters. More precisely, given types `F`, `T1`, `T2`, ...,
343/// `TN` corresponding to expressions `f`, `t1`, `t2`, ..., `tN`,
344/// `bslmf::ResultType<F, T1, T2, ..., TN>::type` is usually the type of the
345/// psuedo-expression <u>INVOKE</u> `(f, t1, t2, ..., tN)`, as defined in section
346/// [func.rquire] of the C++11 standard. If the compiler supports C++11
347/// `decltype` and the psuedo-expression <u>INVOKE</u> `(f, t1, t2, ..., tN)` is
348/// not well-formed, this class provides no `type` member. If `t_FN` is a
349/// class (functor) type and the compiler doesn't support C++11 `decltype`,
350/// the return type is automatically deduced for fundamental types, `void`,
351/// pointers or references to those, or `bsl::nullptr_t` and is deduced by
352/// `bslmf::ResultType<t_FN>::type` otherwise. If deduction fails, this
353/// metafunction yields `bslmf::InvokeResultDeductionFailed`. See
354/// component-level documentation for more detail.
355template <class t_FN, class... t_ARGTYPES>
357: public BloombergLP::bslmf::InvokeResult_BaseCalcUtil<t_FN, t_ARGTYPES...>::
358 BaseType {
359
360 ///Implementation Note
361 ///- - - - - - - - - -
362 // If, by the rules outlined above in the class documentation, this type
363 // defines a member 'type' typedef, that typedef comes from the
364 // 'bslmf::InvokeResult_BaseCalcUtil' specialization from which this class
365 // inherits.
366};
367
368#ifdef BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES
369
370// ALIASES
371
372/// `invoke_result_t` is an alias to the return type of the
373/// `bsl::invoke_result` meta-function. Note, that the `invoke_result_t`
374/// avoids the `::type` suffix and `typename` prefix when we want to use the
375/// result of the meta-function in templates.
376template <class t_FN, class... t_ARGTYPES>
377using invoke_result_t = typename invoke_result<t_FN, t_ARGTYPES...>::type;
378#endif // BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES
379
380#endif
381
382} // close namespace bsl
383
384// ============================================================================
385// TEMPLATE IMPLEMENTATIONS
386// ============================================================================
387
388
389namespace bslmf {
390
391#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES // $var-args=13
392
393/// Forward declaration
394template <bool t_IS_FUNCPTR,
395 bool t_IS_MEMFUNCPTR,
396 bool t_IS_MEMOBJPTR,
397 class t_FN,
398 class... t_ARGTYPES>
399struct InvokeResult_Imp;
400
401 // =========================================
402 // struct template InvokeResult_BaseCalcUtil
403 // =========================================
404
405/// This component-private utility `struct` template provides a nested
406/// typedef, `BaseType`, which is a class type that itself provides a nested
407/// typedef `type` that is the type of the `INVOKE(fn, args...)` expression
408/// given `fn` is an object of the specified `t_FN` type and `args...` are
409/// objects of the specified `t_ARGTYPES...` types. If the
410/// `INVOKE(fn, args...)` expression is not well-formed, `BaseType` provides
411/// no such nested typedef.
412template <class t_FN, class... t_ARGTYPES>
414
415 private:
416 // PRIVATE TYPES
417
418 /// Remove references and cv-qualifiers from `t_FN`, and decay function
419 /// types and array types to pointers. In C++03, treat
420 /// `bslmf::MovableRef<t_T>` as a (movable) reference-qualified `t_T`.
422
423 enum {
424 k_IS_FUNCPTR = BloombergLP::bslmf::IsFunctionPointer<F>::value,
425 k_IS_MEMFUNCPTR= BloombergLP::bslmf::IsMemberFunctionPointer<F>::value,
427 };
428
429 /// `FwdFn` is the type forwarded to `InvokeResult_Imp`. It is `F`
430 /// (a.k.a., `decay_t<t_FN>`) if `F` is a function pointer or
431 /// pointer-to-member and `t_FN` otherwise.
432 typedef typename bsl::conditional<k_IS_FUNCPTR || k_IS_MEMFUNCPTR ||
433 k_IS_MEMOBJPTR,
434 F,
435 t_FN>::type FwdFn;
436
437 public:
438 // TYPES
439
440 /// In C++11 and later, conditionally provides a nested typedef `type`
441 /// that is the type returned by the expression <u>INVOKE</u> `(f, args...)`,
442 /// where `f` is an object of type `t_FN` and `args...` is a list of
443 /// object of types `t_ARGTYPES...`, if the expression is well formed.
444 /// In C++03, provide a nested typed `type` that is the type returned by
445 /// the same invoke expression if the type can be deduced, and is
446 /// `InvokeResultDeductionFailed` otherwise. Note that in C++11 and
447 /// later, `type` is never `InvokeResultDeductionFailed`.
448 typedef typename BloombergLP::bslmf::InvokeResult_Imp<k_IS_FUNCPTR,
449 k_IS_MEMFUNCPTR,
450 k_IS_MEMOBJPTR,
451 FwdFn,
452 t_ARGTYPES...>
454};
455
456#endif
457
458 // ===============================
459 // struct InvokeResult_VoidChecker
460 // ===============================
461
462/// Empty type used to detect void expressions. The size of this type is
463/// the same as `bslmf::Tag<1>`.
464struct InvokeResult_VoidChecker : Tag<true> {
465};
466
467/// Return `InvokeResult_VoidChecker()` if the left argument is of type
468/// cv-`void`; otherwise `bslmf::Tag<false>()`. This overload of the comma
469/// operator is declared but not defined, and is intended to be used in
470/// metafunctions in an unevaluated context to detect void expressions. For
471/// any non-void expression `expr`, `(expr,InvokeResult_VoidChecker())`,
472/// will match this overload and produce a result of type
473/// `bslmf::Tag<false>`. However, `const t_TYPE&` will not match `void`, so
474/// if `expr` is a void expression, the built-in comma operator is matched
475/// and the result will have type `InvokeResult_VoidChecker` (i.e., the
476/// second argument).
477///
478/// Note that Sun CC incorrectly matches this overload for a void
479/// expression, then fails hard. The `enable_if` prevents this match for
480/// Sun CC and any other compilers that may similarly match `void` and is
481/// harmless for compilers that don't.
482template <class t_TYPE>
483typename bsl::enable_if<!bsl::is_void<t_TYPE>::value, Tag<false> >::type
484operator,(const t_TYPE&, InvokeResult_VoidChecker);
485
486/// Metafunction helpers for deducing the return type of an expression.
487struct InvokeResult_Index {
488
489 enum {
490 // Enumeration of possible return types.
491
492 e_VOID,
493 e_BOOL,
494 e_CHAR,
495 e_SCHAR,
496 e_UCHAR,
497 e_CHAR8_T,
498 e_WCHAR_T,
499 e_CHAR16_T,
500 e_CHAR32_T,
501 e_SHORT,
502 e_USHORT,
503 e_INT,
504 e_UNSIGNED,
505 e_LONG,
506 e_ULONG,
507 e_LONG_LONG,
508 e_ULONG_LONG,
509 e_FLOAT,
510 e_DOUBLE,
511 e_LONG_DOUBLE,
512
513 // Pointer to void is special among pointers because it cannot be
514 // dereferenced.
515 e_VOIDPTR,
516 e_CONST_VOIDPTR,
517 e_VOLATILE_VOIDPTR,
518 e_CONST_VOLATILE_VOIDPTR,
519
520 e_NULLPTR_T,
521 e_POINTER, // Any pointer type other than 'void *' or 'nullptr_t'
522 e_OTHER // Anything other than above
523 };
524
525 // CLASS METHODS
526 static bslmf::Tag<e_BOOL> fromVal(bool& );
527 static bslmf::Tag<e_CHAR> fromVal(char& );
528 static bslmf::Tag<e_SCHAR> fromVal(signed char& );
529 static bslmf::Tag<e_UCHAR> fromVal(unsigned char& );
530#ifdef BSLS_COMPILERFEATURES_SUPPORT_UTF8_CHAR_TYPE
531 static bslmf::Tag<e_CHAR8_T> fromVal(char8_t& );
532#endif
533 static bslmf::Tag<e_WCHAR_T> fromVal(wchar_t& );
534#ifdef BSLS_COMPILERFEATURES_SUPPORT_UNICODE_CHAR_TYPES
535 static bslmf::Tag<e_CHAR16_T> fromVal(char16_t& );
536 static bslmf::Tag<e_CHAR32_T> fromVal(char32_t& );
537#endif
538 /// Return a tag type representing the argument type. These functions
539 /// are declared but not defined and are intended to be used in an
540 /// unevaluated context (e.g., within `sizeof`) to convert an expression
541 /// into a compile-time enumeration constant.
542 static bslmf::Tag<e_SHORT> fromVal(short& );
543 static bslmf::Tag<e_USHORT> fromVal(unsigned short& );
544 static bslmf::Tag<e_INT> fromVal(int& );
545 static bslmf::Tag<e_UNSIGNED> fromVal(unsigned& );
546 static bslmf::Tag<e_LONG> fromVal(long& );
547 static bslmf::Tag<e_ULONG> fromVal(unsigned long& );
548 static bslmf::Tag<e_LONG_LONG> fromVal(long long& );
549 static bslmf::Tag<e_ULONG_LONG> fromVal(unsigned long long& );
550 static bslmf::Tag<e_FLOAT> fromVal(float& );
551 static bslmf::Tag<e_DOUBLE> fromVal(double& );
552 static bslmf::Tag<e_LONG_DOUBLE> fromVal(long double& );
553 static bslmf::Tag<e_VOIDPTR> fromVal(void *& );
554 static bslmf::Tag<e_CONST_VOIDPTR> fromVal(const void *& );
555 static bslmf::Tag<e_VOLATILE_VOIDPTR> fromVal(volatile void *& );
556 static bslmf::Tag<e_CONST_VOLATILE_VOIDPTR> fromVal(const volatile void*&);
558 template <class t_TP>
559 static bslmf::Tag<e_POINTER> fromVal(t_TP *&);
560 template <class t_TP>
561 static bslmf::Tag<e_OTHER> fromVal(t_TP&);
562};
563
564/// Metafunction to convert a type index back to a type. For each
565/// specialization of this struct, the `type` member will be the type
566/// corresponding to `index`. For example, if `index` is `e_UCHAR`, then
567/// `InvokeResult_Type<index>::type` is `unsigned char`.
568template <int t_INDEX> struct InvokeResult_Type;
569
570// Turn off bde_verify warnings for "Declaration without tag". Pedantically,
571// every 'type' declared in a metafunction should have the tag '// TYPES', but
572// that breaks up the clean 3-line declaration of each specialization, making
573// the pattern harder to for the eye to follow.
574// BDE_VERIFY pragma: push
575// BDE_VERIFY pragma: -KS00
576template <>
577struct InvokeResult_Type<InvokeResult_Index::e_VOID>
578 { typedef void type; };
579template <>
580struct InvokeResult_Type<InvokeResult_Index::e_BOOL>
581 { typedef bool type; };
582template <>
583struct InvokeResult_Type<InvokeResult_Index::e_CHAR>
584 { typedef char type; };
585template <>
586struct InvokeResult_Type<InvokeResult_Index::e_SCHAR>
587 { typedef signed char type; };
588template <>
589struct InvokeResult_Type<InvokeResult_Index::e_UCHAR>
590 { typedef unsigned char type; };
591#ifdef BSLS_COMPILERFEATURES_SUPPORT_UTF8_CHAR_TYPE
592template <>
593struct InvokeResult_Type<InvokeResult_Index::e_CHAR8_T>
594 { typedef char8_t type; };
595#endif
596template <>
597struct InvokeResult_Type<InvokeResult_Index::e_WCHAR_T>
598 { typedef wchar_t type; };
599#ifdef BSLS_COMPILERFEATURES_SUPPORT_UNICODE_CHAR_TYPES
600template <>
601struct InvokeResult_Type<InvokeResult_Index::e_CHAR16_T>
602 { typedef char16_t type; };
603template <>
604struct InvokeResult_Type<InvokeResult_Index::e_CHAR32_T>
605 { typedef char32_t type; };
606#endif
607template <>
608struct InvokeResult_Type<InvokeResult_Index::e_SHORT>
609 { typedef short type; };
610template <>
611struct InvokeResult_Type<InvokeResult_Index::e_USHORT>
612 { typedef unsigned short type; };
613template <>
614struct InvokeResult_Type<InvokeResult_Index::e_INT>
615 { typedef int type; };
616template <>
617struct InvokeResult_Type<InvokeResult_Index::e_UNSIGNED>
618 { typedef unsigned type; };
619template <>
620struct InvokeResult_Type<InvokeResult_Index::e_LONG>
621 { typedef long type; };
622template <>
623struct InvokeResult_Type<InvokeResult_Index::e_ULONG>
624 { typedef unsigned long type; };
625template <>
626struct InvokeResult_Type<InvokeResult_Index::e_LONG_LONG>
627 { typedef long long type; };
628template <>
629struct InvokeResult_Type<InvokeResult_Index::e_ULONG_LONG>
630 { typedef unsigned long long type; };
631template <>
632struct InvokeResult_Type<InvokeResult_Index::e_FLOAT>
633 { typedef float type; };
634template <>
635struct InvokeResult_Type<InvokeResult_Index::e_DOUBLE>
636 { typedef double type; };
637template <>
638struct InvokeResult_Type<InvokeResult_Index::e_LONG_DOUBLE>
639 { typedef long double type; };
640template <>
641struct InvokeResult_Type<InvokeResult_Index::e_VOIDPTR>
642 { typedef void *type; };
643template <>
644struct InvokeResult_Type<InvokeResult_Index::e_CONST_VOIDPTR>
645 { typedef const void *type; };
646template <>
647struct InvokeResult_Type<InvokeResult_Index::e_VOLATILE_VOIDPTR>
648 { typedef volatile void *type; };
649template <>
650struct InvokeResult_Type<InvokeResult_Index::e_CONST_VOLATILE_VOIDPTR>
651 { typedef const volatile void *type; };
652template <>
653struct InvokeResult_Type<InvokeResult_Index::e_NULLPTR_T>
654 { typedef bsl::nullptr_t type; };
655template <>
656struct InvokeResult_Type<InvokeResult_Index::e_POINTER>
657 { typedef void *type; };
658template <>
659struct InvokeResult_Type<InvokeResult_Index::e_OTHER>
660 { typedef InvokeResultDeductionFailed type; };
661// Re-enable warnings for "Declaration without tag"
662// BDE_VERIFY pragma: pop
663
664/// Utility metaprogramming functions inherited by other metaprogramming
665/// classes.
666struct InvokeResult_ImpUtils
667{
668
669 // TYPES
670
671 /// Type convertible from any lvalue type. Used for overload resolution
672 /// in metafunctions.
673 struct AnyLvalue {
674
675 // CREATORS
676
677 /// (Declared but not defined) Convert from any lvalue argument.
678 template <class t_TP>
679 AnyLvalue(volatile t_TP&);
680 };
681
682 /// Type convertible from any rvalue type. Used for overload resolution
683 /// in metafunctions.
684 struct AnyRvalue {
685
686 // CREATORS
687#ifdef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
688 /// (Declared but not defined) Convert from any rvalue argument.
689 template <class t_TP>
690 AnyRvalue(
691 t_TP&&,
693 int>::type = 0);
694#else
695 template <class t_TP>
697 // (Declared but not defined) Convert from any rvalue argument.
698 // This constructor will also match lvalue arguments, but is used
699 // in a context where 'AnyLValue' is a better conversion path.
700#endif
701 };
702
703 // CLASS METHODS
704#ifdef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
705 /// Return a reference to the specified `t_SOME_TYPE` template parameter
706 /// type; if `t_SOME_TYPE` is an rvalue, then the returned reference is
707 /// an rvalue reference. This function is declared but not defined and
708 /// is intended to be called in an unevaluated context. Because there
709 /// is no definition, the available constructors for `t_SOME_TYPE` are
710 /// irrelevant.
711 template <class t_SOME_TYPE>
712 static typename bsl::add_rvalue_reference<t_SOME_TYPE>::type myDeclval();
713#else
714 template <class t_SOME_TYPE>
715 static t_SOME_TYPE myDeclval();
716 // Return an object of the specified 't_SOME_TYPE' template parameter
717 // type. This function is declared but not defined and is intended to
718 // be called in an unevaluated context. Because there is no
719 // definition, the available constructors for 't_SOME_TYPE' are
720 // irrelevant.
721#endif
722
723 /// (Declared but not defined) Return `bslmf::Tag<false>()` if the
724 /// first argument is an rvalue and `bslmf::Tag<true>()` if it is
725 /// lvalue. In actual use, the second argument is always a literal
726 /// `int`, which causes the second overload to be preferred in case of
727 /// ambiguity.
728 static bslmf::Tag<false> checkLvalue(AnyRvalue, ...);
729 static bslmf::Tag<true > checkLvalue(AnyLvalue, int);
730
731 /// (Declared but not defined) Return `bslmf::Tag<true>()` if the
732 /// argument is `const`-qualified and `bslmf::Tag<false>()` otherwise.
733 template <class t_TP>
734 static bslmf::Tag<false> checkConst(t_TP&);
735 template <class t_TP>
736 static bslmf::Tag<true> checkConst(const t_TP&);
737
738 /// (Declared but not defined) Return `bslmf::Tag<true>()` if the
739 /// argument is `volatile`-qualified and `bslmf::Tag<false>()`
740 /// otherwise. Note that if `t_TP` is both const- and
741 /// volatile-qualified, it will not match `volatile t_TP&`, hence the
742 /// need for the const overloads.
743 template <class t_TP>
744 static bslmf::Tag<false> checkVolatile(t_TP&);
745 template <class t_TP>
746 static bslmf::Tag<false> checkVolatile(const t_TP&);
747 template <class t_TP>
748 static bslmf::Tag<true> checkVolatile(volatile t_TP&);
749 template <class t_TP>
750 static bslmf::Tag<true> checkVolatile(const volatile t_TP&);
751
752 /// (Declared but not defined) Return the argument, with cv-qualifiers
753 /// removed.
754 template <class t_TP>
755 static t_TP& uncv(const t_TP&);
756 template <class t_TP>
757 static t_TP& uncv(const volatile t_TP&);
758
759 /// If the argument type `t_TP` is pointer to type `X`, where `X` is not
760 /// cv-`void`, return a reference to `X`; otherwise return a reference
761 /// to `t_TP`. Note that these functions are declared but not defined
762 /// and are intended to be called only in an unevaluated context.
763 template <class t_TP>
764 static t_TP& unpoint(t_TP&);
765 template <class t_TP>
766 static const t_TP& unpoint(const t_TP&);
767 template <class t_TP>
768 static typename bsl::enable_if<!bsl::is_void<t_TP>::value, t_TP>::type&
769 unpoint(t_TP *&);
770 template <class t_TP>
771 static typename bsl::enable_if<!bsl::is_void<t_TP>::value, t_TP>::type&
772 unpoint(t_TP *const&);
773 template <class t_TP>
774 static typename bsl::enable_if<!bsl::is_void<t_TP>::value, t_TP>::type&
775 unpoint(t_TP *volatile&);
776 template <class t_TP>
777 static typename bsl::enable_if<!bsl::is_void<t_TP>::value, t_TP>::type&
778 unpoint(t_TP *const volatile&);
779};
780
781/// Starting with type, `t_UNQUAL_TYPE`, generate a new type by applying the
782/// following steps in order:
783///
784/// 1. If the specified `t_IS_CONST` parameter is true, apply
785/// `bsl::add_const`; otherwise leave unchanged.
786/// 2. If the specified `t_IS_VOLATILE` parameter is true, apply
787/// `bsl::add_volatile`; otherwise leave unchanged.
788/// 3. If the specified `t_IS_LVALUE` parameter is true, apply
789/// `bsl::add_lvalue_reference`; otherwise leave unchanged.
790///
791/// Set the `type` member to the resulting type.
792template <class t_UNQUAL_TYPE,
793 bool t_IS_CONST,
794 bool t_IS_VOLATILE,
795 bool t_IS_LVALUE>
796struct InvokeResult_AddCVRef {
797
798 private:
799 // PRIVATE TYPES
800 typedef
801 typename bsl::conditional<t_IS_CONST,
803 t_UNQUAL_TYPE>::type CQualType;
804
805 typedef
806 typename bsl::conditional<t_IS_VOLATILE,
808 CQualType>::type CVQualType;
809
810 public:
811 // TYPES
812 typedef typename bsl::conditional<
813 t_IS_LVALUE,
815 CVQualType>::type type;
816};
817
818#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES // $var-args=13
819
820#ifndef BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS
821template <bool /* IS_VOID */, class t_FN, class... t_ARGTYPES>
822struct InvokeResult_FunctorDeduction : InvokeResult_ImpUtils {
823 // Deduce return type of 't_FN(t_ARGTYPES...)'. This template is
824 // instantiated only when 't_FN' is of class type (i.e., a functor). This
825 // primary template is selected when 't_FN(t_ARGTYPES...)' is not 'void'.
826 // Note that this template is not defined in C++11 mode (if 'decltype'
827 // exists).
828
829 typedef typename bsl::decay<t_FN>::type F;
830 // Remove references and cv-qualifiers from 't_FN', and decay function
831 // types and array types to pointers.
832
833 enum {
834 // In an unevaluated context ('BSLMF_TAG_TO_INT'), "invoke"
835 // 'myDeclval<t_FN>()(myDeclval<t_ARGTYPES>()...)' and use overloading
836 // to deduce the type and other attributes of the return value.
837
838 k_INDEX = BSLMF_TAG_TO_INT(InvokeResult_Index::fromVal(
839 uncv(myDeclval<t_FN>()(myDeclval<t_ARGTYPES>()...)))),
840 k_IS_POINTER = (k_INDEX == InvokeResult_Index::e_POINTER),
841 k_IS_LVALUE = BSLMF_TAG_TO_INT(
842 checkLvalue(myDeclval<t_FN>()(myDeclval<t_ARGTYPES>()...), 0)),
843 k_IS_CONST_PTR = k_IS_POINTER &&
844 BSLMF_TAG_TO_INT(checkConst(
845 myDeclval<t_FN>()(myDeclval<t_ARGTYPES>()...))),
846 k_IS_VOLATILE_PTR = k_IS_POINTER &&
847 BSLMF_TAG_TO_INT(checkVolatile(myDeclval<t_FN>()(
848 myDeclval<t_ARGTYPES>()...))),
849 k_TARGET_INDEX = BSLMF_TAG_TO_INT(InvokeResult_Index::fromVal(
850 uncv(unpoint(myDeclval<t_FN>()(myDeclval<t_ARGTYPES>()...))))),
851 k_IS_CONST_TARGET = BSLMF_TAG_TO_INT(checkConst(
852 unpoint(myDeclval<t_FN>()(myDeclval<t_ARGTYPES>()...)))),
853 k_IS_VOLATILE_TARGET = BSLMF_TAG_TO_INT(checkVolatile(
854 unpoint(myDeclval<t_FN>()(myDeclval<t_ARGTYPES>()...)))),
855 k_CANT_DEDUCE_TYPE = (k_TARGET_INDEX ==
856 (int)InvokeResult_Index::e_OTHER)
857 };
858
859 typedef typename bsl::conditional<
860 ! k_CANT_DEDUCE_TYPE,
861 typename InvokeResult_Type<k_TARGET_INDEX>::type,
863 >::type UnqualTargetType;
864 // The deduced result after stripping off pointer, reference, and
865 // cv-qualifiers. The 'TARGET_INDEX' indicates the fundamental type of
866 // the target result. If the target could not be deduced (i.e.,
867 // 'TARGET_INDEX == e_OTHER), then attempt to find the result by
868 // looking for a 'result_type' or 'ResultType' alias in 't_FN'; failing
869 // that, use 'InvokeResultDeductionFailed'.
870
871 typedef typename
872 InvokeResult_AddCVRef<UnqualTargetType,
873 static_cast<bool>(k_IS_CONST_TARGET)
874 && ! static_cast<bool>(k_CANT_DEDUCE_TYPE),
875 static_cast<bool>(k_IS_VOLATILE_TARGET)
876 && ! static_cast<bool>(k_CANT_DEDUCE_TYPE),
877 false>::type CVQualTargetType;
878 // The deduced target after adding back previously-stripped cv
879 // qualifiers, if any. Note that if the expression yielded a pointer
880 // type, these cv qualifiers apply to the target of the pointer, not
881 // the pointer itself.
882
883 typedef typename
885 && ! static_cast<bool>(k_CANT_DEDUCE_TYPE),
887 CVQualTargetType>::type UnqualType;
888 // The deduced result after adding back previously-stripped pointers,
889 // if any.
890
891 typedef typename
892 InvokeResult_AddCVRef<
893 UnqualType,
894 static_cast<bool>(k_IS_CONST_PTR)
895 && ! static_cast<bool>(k_CANT_DEDUCE_TYPE),
896 static_cast<bool>(k_IS_VOLATILE_PTR)
897 && ! static_cast<bool>(k_CANT_DEDUCE_TYPE),
898 static_cast<bool>(k_IS_LVALUE)
899 && ! static_cast<bool>(k_CANT_DEDUCE_TYPE)>::type Qtype;
900 // The deduced result after adding back previously-stripped cv
901 // qualifiers and references. Note that if the result is a pointer,
902 // the cv qualifiers apply to the pointer, not to the target.
903
904 typedef typename bsl::conditional<static_cast<bool>(k_IS_LVALUE), Qtype,
905 typename bsl::remove_cv<Qtype>::type>::type type;
906 // The final deduced result type. If the type is not a reference,
907 // top-level cv qualifiers are stripped off.
908};
909
910template <class t_FN, class... t_ARGTYPES>
911struct InvokeResult_FunctorDeduction<true /* IS_VOID */, t_FN, t_ARGTYPES...> {
912 // Deduce return type of 't_FN(t_ARGTYPES...)'. This template is
913 // instantiated only when 't_FN' is of class type (i.e., a functor). This
914 // specialization is selected when 't_FN(t_ARGTYPES...)' is cv-'void'.
915
916 typedef void type;
917};
918#endif // !BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS
919
920#endif
921
922/// This metafunction determines which cv qualifiers and reference
923/// qualifiers should be propagated from the first argument of
924/// @ref invoke_result . This primary template is instantiated when
925/// `t_ARG_TYPE` is the same or is derived from `t_MEMOF_CLASS`. The
926/// constant `k_IS_LVALUE` is true iff `t_ARG_TYPE` is an lvalue reference;
927/// the constant `k_IS_CONST` is true iff `t_ARG_TYPE` is const-qualified;
928/// and the constant `k_IS_VOLATILE` is true iff `t_ARG_TYPE` is
929/// volatile-qualified.
930template <class t_MEMOF_CLASS,
931 class t_ARG_TYPE,
932 bool t_IS_DERIVED = bsl::is_convertible<
934 typename bsl::decay<t_MEMOF_CLASS>::type *>::value>
935struct InvokeResult_MemPtrArgQualifiers {
936
937 // TYPES
938 enum {
940 k_IS_CONST = bsl::is_const<
941 typename bsl::remove_reference<t_ARG_TYPE>::type>::value,
942 k_IS_VOLATILE = bsl::is_volatile<
943 typename bsl::remove_reference<t_ARG_TYPE>::type>::value
944 };
945};
946
947/// This metafunction determines which cv qualifiers and reference
948/// qualifiers should be propagated from the first argument of
949/// @ref invoke_result .
950///
951/// This specialization is instantiated when `t_ARG_TYPE` is not derived
952/// from `t_MEMOF_CLASS` and is assumed to be a pointer or smart pointer
953/// type. If type `A` is the result of dereferencing an object of type
954/// `t_ARG_TYPE`, then the constant `k_IS_LVALUE` is true iff `A` is an
955/// lvalue reference; the constant `k_IS_CONST` is true iff `A` is a
956/// const-qualified reference; and the constant `k_IS_VOLATILE` is true iff
957/// `A` is a volatile-qualified reference.
958template <class t_MEMOF_CLASS, class t_ARG_TYPE>
959struct InvokeResult_MemPtrArgQualifiers<t_MEMOF_CLASS, t_ARG_TYPE, false>
960: InvokeResult_ImpUtils {
961
962#ifdef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
963 private:
964 // CLASS METHODS
965
966 /// (Declared but not defined.) Return an lvalue reference
967 /// corresponding of the specified `t_TP` type, which is deduced from
968 /// the specified unnamed argument. If the argument is an lvalue, the
969 /// return type is identical to the argument type. If the argument is
970 /// an rvalue, the return type is an lvalue to the argument type with
971 /// the same cv qualifiers. This function is useful for avoiding too
972 /// many redundant overloads in metafunctions that determine cv
973 /// qualifications, etc.
974 template <class t_TP>
975 static t_TP& tolvalue(t_TP&&);
976
977 public:
978 // TYPES
979 enum {k_IS_LVALUE = BSLMF_TAG_TO_INT(checkLvalue(*myDeclval<t_ARG_TYPE>(),
980 0)),
981 k_IS_CONST =
982 BSLMF_TAG_TO_INT(checkConst(tolvalue(*myDeclval<t_ARG_TYPE>()))),
983 k_IS_VOLATILE = BSLMF_TAG_TO_INT(
984 checkVolatile(tolvalue(*myDeclval<t_ARG_TYPE>())))};
985#else
986 public:
987 // TYPES
988 enum {
989 k_IS_LVALUE = BSLMF_TAG_TO_INT(checkLvalue(*myDeclval<t_ARG_TYPE>(),
990 0)),
991 // In C++03, cv qualifiers are discarded from rvalues.
992 k_IS_CONST = k_IS_LVALUE &&
993 BSLMF_TAG_TO_INT(checkConst(*myDeclval<t_ARG_TYPE>())),
994 k_IS_VOLATILE = k_IS_LVALUE && BSLMF_TAG_TO_INT(checkVolatile(
995 *myDeclval<t_ARG_TYPE>()))
996 };
997#endif // BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
998};
999
1000#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES // $var-args=13
1001
1002/// Forward declaration
1003template <class t_VOID_TYPE, class t_FN, class... t_ARGTYPES>
1004struct InvokeResult_FunctorImp;
1005
1006/// Forward declaration
1007template <class t_VOID_TYPE, class t_FN, class... t_ARGTYPES>
1008struct InvokeResult_FuncPtrImp;
1009
1010/// Forward declaration
1011template <class t_FN, class... t_ARGTYPES>
1012struct InvokeResult_MemFuncPtrImp;
1013
1014/// Forward declaration
1015template <class t_FN, class... t_ARGTYPES>
1016struct InvokeResult_MemObjPtrImp;
1017
1018 // ================================
1019 // struct template InvokeResult_Imp
1020 // ================================
1021
1022/// This component-private, partial `struct` template specialization
1023/// provides the implementation of `InvokeResult_Imp` for types that are
1024/// neither function pointers, pointers to member functions, nor pointers to
1025/// member objects.
1026template <bool t_IS_FUNCPTR,
1027 bool t_IS_MEMFUNCPTR,
1028 bool t_IS_MEMOBJPTR,
1029 class t_FN,
1030 class... t_ARGTYPES>
1031struct InvokeResult_Imp : InvokeResult_FunctorImp<void, t_FN, t_ARGTYPES...> {
1032};
1033
1034/// This component-private, partial `struct` template specialization
1035/// provides the implementation of `InvokeResult_Imp` for function pointer
1036/// types.
1037template <class t_FN, class... t_ARGTYPES>
1038struct InvokeResult_Imp<true /* t_IS_FUNCPTR */,
1039 false,
1040 false,
1041 t_FN,
1042 t_ARGTYPES...>
1043: InvokeResult_FuncPtrImp<void, t_FN, t_ARGTYPES...> {
1044};
1045
1046/// This component-private, partial `struct` template specialization
1047/// provides the implementation of `InvokeResult_Imp` for pointer to member
1048/// function types.
1049template <class t_FN, class... t_ARGTYPES>
1050struct InvokeResult_Imp<false,
1051 true /* t_IS_MEMFUNCPTR */,
1052 false,
1053 t_FN,
1054 t_ARGTYPES...>
1055: InvokeResult_MemFuncPtrImp<t_FN, t_ARGTYPES...> {
1056};
1057
1058/// This component-private, partial `struct` template specialization
1059/// provides the implementation of `InvokeResult_Imp` for pointer to member
1060/// object types.
1061template <class t_FN, class... t_ARGTYPES>
1062struct InvokeResult_Imp<false,
1063 false,
1064 true /* t_IS_MEMOBJPTR */,
1065 t_FN,
1066 t_ARGTYPES...>
1067: InvokeResult_MemObjPtrImp<t_FN, t_ARGTYPES...> {
1068};
1069
1070 // =======================================
1071 // struct template InvokeResult_FunctorImp
1072 // =======================================
1073
1074#ifdef BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS
1075/// Implementation of `invoke_result<t_FN, t_ARGTYPES...>`. This
1076/// specialization is instantiated in C++11 and later when `t_FN` is neither
1077/// a pointer-to-function, pointer-to-member-function, nor
1078/// pointer-to-member-object type, and the `INVOKE(fn, args...)` expression,
1079/// is *not* well-formed given `fn` is an object of the specified `t_FN`
1080/// type and `args...` are objects of the specified `t_ARGTYPES...` types.
1081/// The `INVOKE(fn, args...)` expression in this case is `fn(args...)`.
1082/// Note that this `struct` does not provide a `type` typedef.
1083template <class t_VOID_TYPE, class t_FN, class... t_ARGTYPES>
1084struct InvokeResult_FunctorImp {
1085};
1086
1087/// Implementation of `invoke_result<t_FN, t_ARGTYPES...>`. This
1088/// specialization is instantiated in C++11 and later when `t_FN` is neither
1089/// a pointer-to-function, pointer-to-member-function, nor
1090/// pointer-to-member-object type, and the `INVOKE(fn, args...)` expression
1091/// is well-formed given `fn` is an object of the specified `t_FN` type and
1092/// `args...` are objects of the specified `t_ARGTYPES...` types. The
1093/// `INVOKE(fn, args...)` expression in this case is `fn(args...)`.
1094template <class t_FN, class... t_ARGTYPES>
1095struct InvokeResult_FunctorImp<
1096 typename bslmf::VoidType<decltype(InvokeResult_ImpUtils::myDeclval<t_FN>()(
1097 InvokeResult_ImpUtils::myDeclval<t_ARGTYPES>()...))>::type,
1098 t_FN,
1099 t_ARGTYPES...> : InvokeResult_ImpUtils {
1100
1101 // TYPES
1102
1103 /// For C++11 and later, the type of the `INVOKE(fn, args...)`
1104 /// expression given `fn` is an object of the specified `t_FN` type and
1105 /// `args...` are objects of the specified `t_ARGTYPES...` types. The
1106 /// `INVOKE(fn, args...)` expression in this case is `fn(args...)`.
1107 typedef decltype(myDeclval<t_FN>()(myDeclval<t_ARGTYPES>()...)) type;
1108};
1109#else // ! BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS
1110template <class t_VOID_TYPE, class t_FN, class... t_ARGTYPES>
1111struct InvokeResult_FunctorImp : InvokeResult_ImpUtils {
1112 // Implementation of 'invoke_result<t_FN, t_ARGTYPES...>'. This
1113 // specialization is instantiated in C++03 when 't_FN' is neither a
1114 // pointer-to-function, pointer-to-member-function, nor
1115 // pointer-to-member-object type.
1116
1117 // TYPES
1118 enum {
1119 // Determine if 'myDeclval<t_FN>()(myDeclval<t_ARGTYPES>()...)' is a
1120 // void expression by invoking the overloaded comma operator using a
1121 // 'InvokeResult_VoidChecker' as the second argument. If the
1122 // expression is of void type, then the built-in comma operator will
1123 // yield 'InvokeResult_VoidChecker', otherwise the overloaded comma
1124 // operator will yield 'bslmf::Tag<false>'
1125 k_IS_VOID = BSLMF_TAG_TO_INT((
1126 myDeclval<t_FN>()(myDeclval<t_ARGTYPES>()...),
1127 InvokeResult_VoidChecker()))
1128 };
1129
1130 typedef typename InvokeResult_FunctorDeduction<k_IS_VOID,
1131 t_FN,
1132 t_ARGTYPES...>::type type;
1133 // For C++03, the result of invoking
1134 // 'myDeclval<t_FN>()(myDeclval<t_ARGTYPES>()...)' if it can be deduced
1135 // without 'decltype'; otherwise 'InvokeResultDeductionFailed'.
1136};
1137#endif // BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS
1138
1139 // =======================================
1140 // struct template InvokeResult_FuncPtrImp
1141 // =======================================
1142
1143#ifdef BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS
1144/// Implementation of `invoke_result<t_FN, t_ARGTYPES...>`. This
1145/// specialization is instantiated in C++11 and later when `t_FN` is a
1146/// pointer-to-function type, and the `INVOKE(fn, args...)` expression is
1147/// *not* well-formed given `fn` is an object of the specified `t_FN` type
1148/// and `args...` are objects of the specified `t_ARGTYPES...` types. The
1149/// `INVOKE(fn, args...)` expression in this case is `fn(args...)`. Note
1150/// that this `struct` does not provide a `type` typedef.
1151template <class t_VOID_TYPE, class t_FN, class... t_ARGTYPES>
1152struct InvokeResult_FuncPtrImp {
1153};
1154
1155/// Implementation of `invoke_result<t_FN, t_ARGTYPES...>`. This
1156/// specialization is instantiated in C++11 and later when `t_FN` is a
1157/// pointer-to-function type, and the `INVOKE(fn, args...)` expression is
1158/// well-formed given `fn` is an object of the specified `t_FN` type and
1159/// `args...` are objects of the specified `t_ARGTYPES...` types. The
1160/// `INVOKE(fn, args...)` expression in this case is `fn(args...)`.
1161template <class t_FN, class... t_ARGTYPES>
1162struct InvokeResult_FuncPtrImp<
1163 typename bslmf::VoidType<decltype(InvokeResult_ImpUtils::myDeclval<t_FN>()(
1164 InvokeResult_ImpUtils::myDeclval<t_ARGTYPES>()...))>::type,
1165 t_FN,
1166 t_ARGTYPES...> : InvokeResult_ImpUtils {
1167
1168 // TYPES
1169
1170 /// For C++11 and later, the type of result of the `INVOKE(fn, args...)`
1171 /// expression where `fn` is an object of the specified `t_FN` type, and
1172 /// `args...` are objects of the specified `t_ARGTYPES...` types. The
1173 /// `INVOKE(fn, args...)` expression in this case is is `fn(args...)`.
1174 typedef decltype(myDeclval<t_FN>()(myDeclval<t_ARGTYPES>()...)) type;
1175};
1176#else // ! BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS
1177template <class t_VOID_TYPE, class t_FN, class... t_ARGTYPES>
1178struct InvokeResult_FuncPtrImp {
1179 // Implementation of 'invoke_result<t_FN, t_ARGTYPES...>. This
1180 // specialization is instantiated in C++03 when 't_FN' is a
1181 // pointer-to-function type. Note that this C++03 implementation does not
1182 // check whether 't_ARGTYPES...' are valid for 't_FN'.
1183
1185 // The return value of the function pointed-to by 't_FN'.
1186
1187 typedef typename bsl::conditional<
1189 QType,
1190 typename bsl::remove_cv<QType>::type>::type type;
1191 // The return value of the function pointed-to by 't_FN'. If the type
1192 // is a scalar rvalue, cv qualifications are stripped off.
1193};
1194#endif // BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS
1195
1196 // ==========================================
1197 // struct template InvokeResult_MemFuncPtrImp
1198 // ==========================================
1199
1200#ifdef BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS
1201/// Forward declaration.
1202template <class t_VOID_TYPE,
1203 bool t_ARG1_DERIVES_FROM_CLASS,
1204 bool t_ARG1_IS_REFERENCE_WRAPPER,
1205 class t_FN,
1206 class t_ARG1TYPE,
1207 class... t_ARGTYPES>
1208struct InvokeResult_MemFuncPtrImpDispatch;
1209
1210// SPECIALIZATIONS
1211
1212/// Implementation of `invoke_result<t_FN, t_ARGTYPES...>`. This
1213/// specialization is instantiated in C++11 and later when `t_FN` is a
1214/// pointer-to-member-function type, and the `t_ARGTYPES...` pack is empty.
1215/// Note that this `struct` does not provide a `type` typedef.
1216template <class t_FN>
1217struct InvokeResult_MemFuncPtrImp<t_FN> {
1218};
1219
1220/// Implementation of `invoke_result<t_FN, t_ARGTYPES...>`. This
1221/// specialization is instantiated in C++11 and later when `t_FN` is a
1222/// pointer-to-member-function type, and the `t_ARGTYPES...` pack contains
1223/// 1 type or more.
1224template <class t_FN, class t_ARG1TYPE, class... t_ARGTYPES>
1225struct InvokeResult_MemFuncPtrImp<t_FN, t_ARG1TYPE, t_ARGTYPES...>
1226: InvokeResult_MemFuncPtrImpDispatch<
1227 void,
1228 IsAccessibleBaseOf<
1229 typename MemberFunctionPointerTraits<t_FN>::ClassType,
1230 typename bsl::remove_reference<t_ARG1TYPE>::type>::value,
1231 IsReferenceWrapper<typename bsl::remove_const<
1232 typename bsl::remove_reference<t_ARG1TYPE>::type>::type>::value,
1233 t_FN,
1234 t_ARG1TYPE,
1235 t_ARGTYPES...> {
1236};
1237#else // ! BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS
1238template <class t_FN, class... t_ARGTYPES>
1239struct InvokeResult_MemFuncPtrImp<t_FN, t_ARGTYPES...> {
1240 // Implementation of 'invoke_result<t_FN, t_ARGTYPES...>. This
1241 // specialization is instantiated in C++03 when 't_FN' is a
1242 // pointer-to-member-function type.
1243
1244 typedef typename MemberFunctionPointerTraits<t_FN>::ResultType QType;
1245 // The return value of the function pointed-to by 't_FN'.
1246
1247 typedef typename bsl::conditional<
1249 QType,
1250 typename bsl::remove_cv<QType>::type>::type type;
1251 // The return value of the function pointed-to by 't_FN'. If the type
1252 // is a scalar rvalue, cv qualifications are stripped off.
1253};
1254#endif // BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS
1255
1256 // ==================================================
1257 // struct template InvokeResult_MemFuncPtrImpDispatch
1258 // ==================================================
1259
1260#ifdef BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS
1261/// Implementation of `invoke_result<t_FN, t_ARG1TYPE, t_ARGTYPES...>`.
1262/// This specialization is instantiated in C++11 and later when `t_FN` is a
1263/// pointer-to-member-function type, and the `INVOKE(fn, arg1, args...)`
1264/// expression is *not* well-formed given `fn` is an object of the specified
1265/// `t_FN` type and `arg1, args...` are objects of the specified
1266/// `t_ARG1TYPE, t_ARGTYPES...` types. Note that this `struct` does not
1267/// provide a `type` typedef.
1268template <class t_VOID_TYPE,
1269 bool t_ARG1_DERIVES_FROM_CLASS,
1270 bool t_ARG1_IS_REFERENCE_WRAPPER,
1271 class t_FN,
1272 class t_ARG1TYPE,
1273 class... t_ARGTYPES>
1274struct InvokeResult_MemFuncPtrImpDispatch {
1275};
1276
1277/// Implementation of `invoke_result<t_FN, t_ARG1TYPE, t_ARGTYPES...>`.
1278/// This specialization is instantiated in C++11 and later when `t_FN` is a
1279/// pointer-to-member-function type, `t_ARG1TYPE` is neither a class type
1280/// that derives from the class type of `t_FN` nor a specialization of
1281/// `bsl::reference_wrapper`, and the `INVOKE(fn, arg1, args...)` expression
1282/// is well-formed given `fn` is an object of the specified `t_FN` type and
1283/// `arg1, args...` are objects of the specified `t_ARG1TYPE, t_ARGTYPES...`
1284/// types. The `INVOKE(fn, arg1, args...)` expression in this case is
1285/// `((*arg1).*fn)(args...)`.
1286template <class t_FN, class t_ARG1TYPE, class... t_ARGTYPES>
1287struct InvokeResult_MemFuncPtrImpDispatch<
1288 typename bslmf::VoidType<
1289 decltype(((*InvokeResult_ImpUtils::myDeclval<t_ARG1TYPE>()).*
1290 InvokeResult_ImpUtils::myDeclval<t_FN>())(
1291 InvokeResult_ImpUtils::myDeclval<t_ARGTYPES>()...))>::type,
1292 /* t_ARG1_DERIVES_FROM_CLASS */ false,
1293 /* t_ARG1_IS_REFERENCE_WRAPPER */ false,
1294 t_FN,
1295 t_ARG1TYPE,
1296 t_ARGTYPES...> : InvokeResult_ImpUtils {
1297
1298 // TYPES
1299
1300 /// For C++11 and later, the type of the `INVOKE(fn, args...)`
1301 /// expression where `fn` is an object of the specified `t_FN` type, and
1302 /// `arg1, args...` are objects of the specified
1303 /// `t_ARG1TYPE, t_ARGTYPES...` types. The `INVOKE(fn, arg1, args...)`
1304 /// expression in this case is `((*arg1).*fn)(args...)`.
1305 typedef decltype(((*myDeclval<t_ARG1TYPE>()).*
1306 myDeclval<t_FN>())(myDeclval<t_ARGTYPES>()...)) type;
1307};
1308
1309/// Implementation of `invoke_result<t_FN, t_ARGTYPES...>`. This
1310/// specialization is instantiated in C++11 and later when `t_FN` is a
1311/// pointer-to-member-function type, `t_ARG1TYPE` is a class type that
1312/// derives from the class type of `t_FN`, and the
1313/// `INVOKE(fn, arg1, args...)` expression is well-formed given `fn` is an
1314/// object of the specified `t_FN` type and `arg1, args...` are objects of
1315/// the specified `t_ARG1TYPE, t_ARGTYPES...` types. The
1316/// `INVOKE(fn, arg1, args...)` expression in this case is
1317/// `(arg1.*fn)(args...)`.
1318template <class t_FN, class t_ARG1TYPE, class... t_ARGTYPES>
1319struct InvokeResult_MemFuncPtrImpDispatch<
1320 typename bslmf::VoidType<
1321 decltype((InvokeResult_ImpUtils::myDeclval<t_ARG1TYPE>().*
1322 InvokeResult_ImpUtils::myDeclval<t_FN>())(
1323 InvokeResult_ImpUtils::myDeclval<t_ARGTYPES>()...))>::type,
1324 /* t_ARG1_DERIVES_FROM_CLASS */ true,
1325 /* t_ARG1_IS_REFERENCE_WRAPPER */ false,
1326 t_FN,
1327 t_ARG1TYPE,
1328 t_ARGTYPES...> : InvokeResult_ImpUtils {
1329
1330 // TYPES
1331
1332 /// For C++11 and later, the type of the `INVOKE(fn, arg1, args...)`
1333 /// expression where `fn` is an object of the specified `t_FN` type, and
1334 /// `arg1, args...` are objects of the specified
1335 /// `t_ARG1TYPE, t_ARGTYPES...` types. The `INVOKE(fn, arg1, args...)`
1336 /// expression in this case is `(arg1.*fn)(args...)`.
1337 typedef decltype((myDeclval<t_ARG1TYPE>().*
1338 myDeclval<t_FN>())(myDeclval<t_ARGTYPES>()...)) type;
1339};
1340
1341/// Implementation of `invoke_result<t_FN, t_ARGTYPES...>`. This
1342/// specialization is instantiated in C++11 and later when `t_FN` is a
1343/// pointer-to-member-function type, `t_ARG1TYPE` is a specialization of
1344/// `bsl::reference_wrapper`, and the `INVOKE(fn, arg1, args...)` expression
1345/// is well-formed given `fn` is an object of the specified `t_FN` type and
1346/// `arg1, args...` are objects of the specified `t_ARG1TYPE, t_ARGTYPES...`
1347/// types. The `INVOKE(fn, arg1, args...)` expression in this case is
1348/// `(arg1.get().*fn)(args...)`.
1349template <class t_FN, class t_ARG1TYPE, class... t_ARGTYPES>
1350struct InvokeResult_MemFuncPtrImpDispatch<
1351 typename bslmf::VoidType<
1352 decltype((InvokeResult_ImpUtils::myDeclval<t_ARG1TYPE>().get().*
1353 InvokeResult_ImpUtils::myDeclval<t_FN>())(
1354 InvokeResult_ImpUtils::myDeclval<t_ARGTYPES>()...))>::type,
1355 /* t_ARG1_DERIVES_FROM_CLASS */ false,
1356 /* t_ARG1_IS_REFERENCE_WRAPPER */ true,
1357 t_FN,
1358 t_ARG1TYPE,
1359 t_ARGTYPES...> : InvokeResult_ImpUtils {
1360
1361 // TYPES
1362
1363 /// For C++11 and later, the type of the `INVOKE(fn, arg1, args...)`
1364 /// expression where `fn` is an object of the specified `t_FN` type, and
1365 /// `arg1, args...` are objects of the specified
1366 /// `t_ARG1TYPE, t_ARGTYPES...` types. The `INVOKE(fn, arg1, args...)`
1367 /// expression in this case is `(arg1.get().*fn)(args...)`.
1368 typedef decltype((myDeclval<t_ARG1TYPE>().get().*
1369 myDeclval<t_FN>())(myDeclval<t_ARGTYPES>()...)) type;
1370};
1371
1372#endif // BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS
1373
1374 // =========================================
1375 // struct template InvokeResult_MemObjPtrImp
1376 // =========================================
1377
1378#ifdef BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS
1379/// Forward declaration.
1380template <class t_VOID_TYPE,
1381 bool t_ARG_DERIVES_FROM_CLASS,
1382 bool t_ARG_IS_REFERENCE_WRAPPER,
1383 class t_FN,
1384 class t_ARGTYPE>
1385struct InvokeResult_MemObjPtrImpDispatch;
1386
1387// SPECIALIZATIONS
1388
1389/// Implementation of `invoke_result<t_FN, t_ARGTYPES...>`. This
1390/// specialization is instantiated in C++11 and later when `t_FN` is a
1391/// pointer-to-member-object type, and the `t_ARGTYPES...` pack is empty or
1392/// contains more than 1 type. Note that this `struct` does not provide a
1393/// `type` typedef.
1394template <class t_FN, class... t_ARGTYPES>
1395struct InvokeResult_MemObjPtrImp {
1396};
1397
1398/// Implementation of `invoke_result<t_FN, t_ARGTYPES...>`. This
1399/// specialization is instantiated in C++11 and later when `t_FN` is a
1400/// pointer-to-member-object type and the `t_ARGTYPES...` pack contains
1401/// exactly 1 type.
1402template <class t_FN, class t_ARGTYPE>
1403struct InvokeResult_MemObjPtrImp<t_FN, t_ARGTYPE>
1404: InvokeResult_MemObjPtrImpDispatch<
1405 void,
1406 IsAccessibleBaseOf<
1407 typename MemberPointerTraits<t_FN>::ClassType,
1408 typename bsl::remove_reference<t_ARGTYPE>::type>::value,
1409 IsReferenceWrapper<typename bsl::remove_const<
1410 typename bsl::remove_reference<t_ARGTYPE>::type>::type>::value,
1411 t_FN,
1412 t_ARGTYPE> {
1413};
1414
1415#else // ! BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS
1416
1417template <class t_FN, class... t_ARGTYPES>
1418struct InvokeResult_MemObjPtrImp {
1419};
1420
1421template <class t_CLASS, class t_RET, class t_ARGTYPE>
1422struct InvokeResult_MemObjPtrImp<t_RET t_CLASS::*, t_ARGTYPE> {
1423 // Implementation of 'invoke_result<t_FN, t_ARGTYPES...>. This
1424 // specialization is instantated in C++03 when 't_FN' is a pointer to data
1425 // member and 't_ARGTYPE' is an rvalue type.
1426
1427 private:
1428 typedef InvokeResult_MemPtrArgQualifiers<t_CLASS, t_ARGTYPE> ArgQualifiers;
1429 // Determine the cv qualifications and reference qualifications from
1430 // 't_ARGTYPE' that should be applied to 't_RET'.
1431
1432 typedef typename InvokeResult_AddCVRef<t_RET,
1433 ArgQualifiers::k_IS_CONST,
1434 ArgQualifiers::k_IS_VOLATILE,
1435 ArgQualifiers::k_IS_LVALUE>::type
1436 cvtype;
1437 // The type of member pointed to by the pointer-to-member-object, with
1438 // cv and reference qualifiers taken from 't_ARGTYPE'.
1439
1440 public:
1441#ifdef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
1442 typedef typename bsl::conditional<
1443 ArgQualifiers::k_IS_LVALUE,
1444 cvtype,
1445 typename bsl::add_rvalue_reference<cvtype>::type>::type type;
1446 // Result type. If rvalue references are supported, data members of
1447 // rvalues are always returned as rvalue references in C++11 and later.
1448#else
1449 typedef cvtype type;
1450 // Rvalue result type.
1451#endif
1452};
1453#endif // BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS
1454
1455 // =================================================
1456 // struct template InvokeResult_MemObjPtrImpDispatch
1457 // =================================================
1458
1459#ifdef BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS
1460/// Implementation of `invoke_result<t_FN, t_ARGTYPE>`. This specialization
1461/// is instantiated in C++11 and later when `t_FN` is a
1462/// pointer-to-member-object type, and the `INVOKE(fn, arg)` expression is
1463/// *not* well-formed given `fn` is an object of the specified `t_FN` type
1464/// and `arg` is an object of the specified `t_ARGTYPE`. Note that this
1465/// `struct` does not provide a `type` typedef.
1466template <class t_VOID_TYPE,
1467 bool t_ARG_DERIVES_FROM_CLASS,
1468 bool t_ARG_IS_REFERENCE_WRAPPER,
1469 class t_FN,
1470 class t_ARGTYPE>
1471struct InvokeResult_MemObjPtrImpDispatch {
1472};
1473
1474/// Implementation of `invoke_result<t_FN, t_ARGTYPE>`. This specialization
1475/// is instantiated in C++11 and later when `t_FN` is a
1476/// pointer-to-member-object type, `t_ARGTYPE` is neither a class type that
1477/// derives from the class type of `t_FN` nor a specialization of
1478/// `bsl::reference_wrapper`, and the `INVOKE(fn, arg)` expression is
1479/// well-formed given `fn` is an object of the specified `t_FN` type and
1480/// `arg` is an object of the specified `t_ARGTYPE` type. The
1481/// `INVOKE(fn, arg)` expression in this case is `(*arg).*fn`.
1482template <class t_FN, class t_ARGTYPE>
1483struct InvokeResult_MemObjPtrImpDispatch<
1484 typename bslmf::VoidType<
1485 decltype((*InvokeResult_ImpUtils::myDeclval<t_ARGTYPE>()).*
1486 InvokeResult_ImpUtils::myDeclval<t_FN>())>::type,
1487 /* t_ARG1_DERIVES_FROM_CLASS */ false,
1488 /* t_ARG1_IS_REFERENCE_WRAPPER */ false,
1489 t_FN,
1490 t_ARGTYPE> : InvokeResult_ImpUtils {
1491
1492 // TYPES
1493 typedef decltype((*myDeclval<t_ARGTYPE>()).*myDeclval<t_FN>()) type;
1494 // For C++11 and later, the type of the 'INVOKE(fn, arg)' expression where
1495 // 'fn' is an object of the specified 't_FN' type, and 'arg' is an object
1496 // of the specified 't_ARGTYPE' type. The 'INVOKE(fn, arg)' expression in
1497 // this case is '(*arg).*fn'.
1498};
1499
1500/// Implementation of `invoke_result<t_FN, t_ARGTYPE>`. This specialization
1501/// is instantiated in C++11 and later when `t_FN` is a
1502/// pointer-to-member-object type, `t_ARGTYPE` is a class type that derives
1503/// from the class type of `t_FN`, and the `INVOKE(fn, arg)` expression is
1504/// well-formed given `fn` is an object of the specified `t_FN` type and
1505/// `arg` is an object of the specified `t_ARGTYPE` type. The
1506/// `INVOKE(fn, arg)` expression in this case is `arg1.*fn`.
1507template <class t_FN, class t_ARGTYPE>
1508struct InvokeResult_MemObjPtrImpDispatch<
1509 typename bslmf::VoidType<
1510 decltype(InvokeResult_ImpUtils::myDeclval<t_ARGTYPE>().*
1511 InvokeResult_ImpUtils::myDeclval<t_FN>())>::type,
1512 /* t_ARG_DERIVES_FROM_CLASS */ true,
1513 /* t_ARG_IS_REFERENCE_WRAPPER */ false,
1514 t_FN,
1515 t_ARGTYPE> : InvokeResult_ImpUtils {
1516
1517 // TYPES
1518 typedef decltype(myDeclval<t_ARGTYPE>().*myDeclval<t_FN>()) type;
1519 // For C++11 and later, the type of the 'INVOKE(fn, arg)' expression where
1520 // 'fn' is an object of the specified 't_FN' type, and 'arg' is an object
1521 // of the specified 't_ARGTYPE' type. The 'INVOKE(fn, arg)' expression in
1522 // this case is 'arg1.*fn'.
1523};
1524
1525/// Implementation of `invoke_result<t_FN, t_ARGTYPE>`. This specialization
1526/// is instantiated in C++11 and later when `t_FN` is a
1527/// pointer-to-member-object type, `t_ARGTYPE` is a specialization of
1528/// `bsl::reference_wrapper`, and the `INVOKE(fn, arg)` expression is
1529/// well-formed given `fn` is an object of the specified `t_FN` type and
1530/// `arg` is an object of the specified `t_ARGTYPE` type. The
1531/// `INVOKE(fn, arg)` expression in this case is `arg.get().*fn`.
1532template <class t_FN, class t_ARGTYPE>
1533struct InvokeResult_MemObjPtrImpDispatch<
1534 typename bslmf::VoidType<
1535 decltype(InvokeResult_ImpUtils::myDeclval<t_ARGTYPE>().get().*
1536 InvokeResult_ImpUtils::myDeclval<t_FN>())>::type,
1537 /* t_ARG1_DERIVES_FROM_CLASS */ false,
1538 /* t_ARG1_IS_REFERENCE_WRAPPER */ true,
1539 t_FN,
1540 t_ARGTYPE> : InvokeResult_ImpUtils {
1541
1542 // TYPES
1543 typedef decltype(myDeclval<t_ARGTYPE>().get().*myDeclval<t_FN>()) type;
1544 // For C++11 and later, the type of the 'INVOKE(fn, arg)' expression where
1545 // 'fn' is an object of the specified 't_FN' type, and 'arg' is an object
1546 // of the specified 't_ARGTYPE' type. The 'INVOKE(fn, arg)' expression in
1547 // this case is 'arg.get().*fn'.
1548};
1549
1550#endif // BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS
1551
1552#endif
1553
1554} // close package namespace
1555
1556
1557#endif // End C++11 code
1558
1559#endif // ! defined(INCLUDED_BSLMF_INVOKERESULT)
1560
1561// ----------------------------------------------------------------------------
1562// Copyright 2018 Bloomberg Finance L.P.
1563//
1564// Licensed under the Apache License, Version 2.0 (the "License");
1565// you may not use this file except in compliance with the License.
1566// You may obtain a copy of the License at
1567//
1568// http://www.apache.org/licenses/LICENSE-2.0
1569//
1570// Unless required by applicable law or agreed to in writing, software
1571// distributed under the License is distributed on an "AS IS" BASIS,
1572// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1573// See the License for the specific language governing permissions and
1574// limitations under the License.
1575// ----------------------------- END-OF-FILE ----------------------------------
1576
1577/** @} */
1578/** @} */
1579/** @} */
decay_imp< U, k_ISARRAY, k_ISFUNC >::type type
Definition bslmf_decay.h:166
Definition bslmf_invokeresult.h:358
#define BSLMF_TAG_TO_INT(BSLMF_EXPR)
Definition bslmf_tag.h:176
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bdlb_printmethods.h:283
BloombergLP::bsls::Nullptr_Impl::Type nullptr_t
Definition bsls_nullptr.h:281
Definition bdlbb_blob.h:576
BloombergLP::bslmf::AddConst_Imp< t_TYPE,!is_reference< t_TYPE >::value &&!is_function< t_TYPE >::value &&!is_const< t_TYPE >::value >::Type type
Definition bslmf_addconst.h:172
t_TYPE & type
This typedef defines the return type of this meta function.
Definition bslmf_addlvaluereference.h:129
BloombergLP::bslmf::AddPointer_Impl< t_TYPE >::type type
Definition bslmf_addpointer.h:175
BloombergLP::bslmf::AddVolatile_Imp< t_TYPE,!is_reference< t_TYPE >::value &&!is_function< t_TYPE >::value &&!is_volatile< t_TYPE >::value >::Type type
Definition bslmf_addvolatile.h:174
Definition bslmf_conditional.h:120
Definition bslmf_enableif.h:525
Definition bslmf_integralconstant.h:244
Definition bslmf_isclass.h:163
Definition bslmf_isconst.h:144
Definition bslmf_isconvertible.h:867
Definition bslmf_islvaluereference.h:125
Definition bslmf_ismemberobjectpointer.h:141
Definition bslmf_isreference.h:137
Definition bslmf_isrvaluereference.h:126
Definition bslmf_isvolatile.h:144
remove_const< typenameremove_volatile< t_TYPE >::type >::type type
Definition bslmf_removecv.h:126
Definition bslmf_functionpointertraits.h:137
Definition bslmf_invokeresult.h:308
InvokeResultDeductionFailed(const t_TYPE &)
Definition bslmf_invokeresult.h:315
Forward declaration.
Definition bslmf_invokeresult.h:413
BloombergLP::bslmf::InvokeResult_Imp< k_IS_FUNCPTR, k_IS_MEMFUNCPTR, k_IS_MEMOBJPTR, FwdFn, t_ARGTYPES... > BaseType
Definition bslmf_invokeresult.h:453
Definition bslmf_invokeresult.h:673
AnyLvalue(volatile t_TP &)
(Declared but not defined) Convert from any lvalue argument.
Definition bslmf_invokeresult.h:684
t_FALLBACK type
Definition bslmf_resulttype.h:260
Definition bslmf_tag.h:163