BDE 4.39.x 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// clang-format off
276// Include version that can be compiled with C++03
277// Generated on Mon Jan 13 08:31:25 2025
278// Command line: sim_cpp11_features.pl bslmf_invokeresult.h
279
280# define COMPILING_BSLMF_INVOKERESULT_H
282# undef COMPILING_BSLMF_INVOKERESULT_H
283
284// clang-format on
285#else
286
287# if defined(BSLS_COMPILERFEATURES_SUPPORT_DECLTYPE)
288// The implementation of C++17 semantics in this component depends upon the
289// use of 'decltype' and expression SFINAE. Note that we have no feature
290// macro to test for expression SFINAE.
291# define BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS 1
292#endif
293
294
295namespace bslmf {
296
297 // ==========================================
298 // class template InvokeResultDeductionFailed
299 // ==========================================
300
301/// When @ref invoke_result cannot deduce the actual return type of a functor
302/// (in C++03 mode), it yields this type as a placeholder. The advantage of
303/// using this placeholder instead of a compilation failure (e.g., using a
304/// static assert) is that the return type of an INVOKE() operation is
305/// often discarded, so our failure to deduce the return type is often
306/// harmless. Since `InvokeResultDeductionFailed` is a return type, it must
307/// be convertible from the actual return type; this conversion is
308/// accomplished by means of a constructor that makes it convertible from
309/// *any* type.
310///
311/// See @ref bslmf_invokeresult
313
314 // CREATORS
315
316 /// Convert from an arbitrary type. The actual argument value is
317 /// discarded.
318 template <class t_TYPE>
320 {
321 }
322};
323
324#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES // $var-args=13
325
326/// Forward declaration
327template <class t_FN, class... t_ARGTYPES>
328struct InvokeResult_BaseCalcUtil;
329
330#endif
331
332} // close package namespace
333
334
335 // ============================
336 // class template invoke_result
337 // ============================
338
339namespace bsl {
340
341#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES // $var-args=13
342
343/// This class is a metafunction that conditionally provides a `type` member
344/// that is the type resulting from invoking an object of the specified
345/// `t_FN` template parameter with arguments of the specified `t_ARGTYPES`
346/// template parameters. More precisely, given types `F`, `T1`, `T2`, ...,
347/// `TN` corresponding to expressions `f`, `t1`, `t2`, ..., `tN`,
348/// `bslmf::ResultType<F, T1, T2, ..., TN>::type` is usually the type of the
349/// psuedo-expression <u>INVOKE</u> `(f, t1, t2, ..., tN)`, as defined in section
350/// [func.rquire] of the C++11 standard. If the compiler supports C++11
351/// `decltype` and the psuedo-expression <u>INVOKE</u> `(f, t1, t2, ..., tN)` is
352/// not well-formed, this class provides no `type` member. If `t_FN` is a
353/// class (functor) type and the compiler doesn't support C++11 `decltype`,
354/// the return type is automatically deduced for fundamental types, `void`,
355/// pointers or references to those, or `bsl::nullptr_t` and is deduced by
356/// `bslmf::ResultType<t_FN>::type` otherwise. If deduction fails, this
357/// metafunction yields `bslmf::InvokeResultDeductionFailed`. See
358/// component-level documentation for more detail.
359template <class t_FN, class... t_ARGTYPES>
361: public BloombergLP::bslmf::InvokeResult_BaseCalcUtil<t_FN, t_ARGTYPES...>::
362 BaseType {
363
364 ///Implementation Note
365 ///- - - - - - - - - -
366 // If, by the rules outlined above in the class documentation, this type
367 // defines a member 'type' typedef, that typedef comes from the
368 // 'bslmf::InvokeResult_BaseCalcUtil' specialization from which this class
369 // inherits.
370};
371
372#ifdef BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES
373
374// ALIASES
375
376/// @ref invoke_result_t is an alias to the return type of the
377/// `bsl::invoke_result` meta-function. Note, that the @ref invoke_result_t
378/// avoids the `::type` suffix and `typename` prefix when we want to use the
379/// result of the meta-function in templates.
380template <class t_FN, class... t_ARGTYPES>
381using invoke_result_t = typename invoke_result<t_FN, t_ARGTYPES...>::type;
382#endif // BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES
383
384#endif
385
386} // close namespace bsl
387
388// ============================================================================
389// TEMPLATE IMPLEMENTATIONS
390// ============================================================================
391
392
393namespace bslmf {
394
395#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES // $var-args=13
396
397/// Forward declaration
398template <bool t_IS_FUNCPTR,
399 bool t_IS_MEMFUNCPTR,
400 bool t_IS_MEMOBJPTR,
401 class t_FN,
402 class... t_ARGTYPES>
403struct InvokeResult_Imp;
404
405 // =========================================
406 // struct template InvokeResult_BaseCalcUtil
407 // =========================================
408
409/// This component-private utility `struct` template provides a nested
410/// typedef, `BaseType`, which is a class type that itself provides a nested
411/// typedef `type` that is the type of the `INVOKE(fn, args...)` expression
412/// given `fn` is an object of the specified `t_FN` type and `args...` are
413/// objects of the specified `t_ARGTYPES...` types. If the
414/// `INVOKE(fn, args...)` expression is not well-formed, `BaseType` provides
415/// no such nested typedef.
416///
417/// See @ref bslmf_invokeresult
418template <class t_FN, class... t_ARGTYPES>
420
421 private:
422 // PRIVATE TYPES
423
424 /// Remove references and cv-qualifiers from `t_FN`, and decay function
425 /// types and array types to pointers. In C++03, treat
426 /// `bslmf::MovableRef<t_T>` as a (movable) reference-qualified `t_T`.
428
429 enum {
430 k_IS_FUNCPTR = BloombergLP::bslmf::IsFunctionPointer<F>::value,
431 k_IS_MEMFUNCPTR= BloombergLP::bslmf::IsMemberFunctionPointer<F>::value,
433 };
434
435 /// `FwdFn` is the type forwarded to `InvokeResult_Imp`. It is `F`
436 /// (a.k.a., `decay_t<t_FN>`) if `F` is a function pointer or
437 /// pointer-to-member and `t_FN` otherwise.
438 typedef typename bsl::conditional<k_IS_FUNCPTR || k_IS_MEMFUNCPTR ||
439 k_IS_MEMOBJPTR,
440 F,
441 t_FN>::type FwdFn;
442
443 public:
444 // TYPES
445
446 /// In C++11 and later, conditionally provides a nested typedef `type`
447 /// that is the type returned by the expression <u>INVOKE</u> `(f, args...)`,
448 /// where `f` is an object of type `t_FN` and `args...` is a list of
449 /// object of types `t_ARGTYPES...`, if the expression is well formed.
450 /// In C++03, provide a nested typed `type` that is the type returned by
451 /// the same invoke expression if the type can be deduced, and is `InvokeResultDeductionFailed` otherwise.
452 ///
453 /// \note Note that in C++11 and
454 /// later, `type` is never `InvokeResultDeductionFailed`.
455 typedef typename BloombergLP::bslmf::InvokeResult_Imp<k_IS_FUNCPTR,
456 k_IS_MEMFUNCPTR,
457 k_IS_MEMOBJPTR,
458 FwdFn,
459 t_ARGTYPES...>
461};
462
463#endif
464
465 // ===============================
466 // struct InvokeResult_VoidChecker
467 // ===============================
468
469/// Empty type used to detect void expressions. The size of this type is
470/// the same as `bslmf::Tag<1>`.
471struct InvokeResult_VoidChecker : Tag<true> {
472};
473
474/// Return `InvokeResult_VoidChecker()` if the left argument is of type
475/// cv-`void`; otherwise `bslmf::Tag<false>()`. This overload of the comma
476/// operator is declared but not defined, and is intended to be used in
477/// metafunctions in an unevaluated context to detect void expressions. For
478/// any non-void expression `expr`, `(expr,InvokeResult_VoidChecker())`,
479/// will match this overload and produce a result of type
480/// `bslmf::Tag<false>`. However, `const t_TYPE&` will not match `void`, so
481/// if `expr` is a void expression, the built-in comma operator is matched
482/// and the result will have type `InvokeResult_VoidChecker` (i.e., the
483/// second argument).
484///
485///
486/// \note Note that Sun CC incorrectly matches this overload for a void
487/// expression, then fails hard. The `enable_if` prevents this match for
488/// Sun CC and any other compilers that may similarly match `void` and is
489/// harmless for compilers that don't.
490template <class t_TYPE>
491typename bsl::enable_if<!bsl::is_void<t_TYPE>::value, Tag<false> >::type
492operator,(const t_TYPE&, InvokeResult_VoidChecker);
493
494/// Metafunction helpers for deducing the return type of an expression.
495///
496/// See @ref bslmf_invokeresult
497struct InvokeResult_Index {
498
499 enum {
500 // Enumeration of possible return types.
501
502 e_VOID,
503 e_BOOL,
504 e_CHAR,
505 e_SCHAR,
506 e_UCHAR,
507 e_CHAR8_T,
508 e_WCHAR_T,
509 e_CHAR16_T,
510 e_CHAR32_T,
511 e_SHORT,
512 e_USHORT,
513 e_INT,
514 e_UNSIGNED,
515 e_LONG,
516 e_ULONG,
517 e_LONG_LONG,
518 e_ULONG_LONG,
519 e_FLOAT,
520 e_DOUBLE,
521 e_LONG_DOUBLE,
522
523 // Pointer to void is special among pointers because it cannot be
524 // dereferenced.
525 e_VOIDPTR,
526 e_CONST_VOIDPTR,
527 e_VOLATILE_VOIDPTR,
528 e_CONST_VOLATILE_VOIDPTR,
529
530 e_NULLPTR_T,
531 e_POINTER, // Any pointer type other than 'void *' or 'nullptr_t'
532 e_OTHER // Anything other than above
533 };
534
535 // CLASS METHODS
536 static bslmf::Tag<e_BOOL> fromVal(bool& );
537 static bslmf::Tag<e_CHAR> fromVal(char& );
538 static bslmf::Tag<e_SCHAR> fromVal(signed char& );
539 static bslmf::Tag<e_UCHAR> fromVal(unsigned char& );
540#ifdef BSLS_COMPILERFEATURES_SUPPORT_UTF8_CHAR_TYPE
541 static bslmf::Tag<e_CHAR8_T> fromVal(char8_t& );
542#endif
543 static bslmf::Tag<e_WCHAR_T> fromVal(wchar_t& );
544#ifdef BSLS_COMPILERFEATURES_SUPPORT_UNICODE_CHAR_TYPES
545 static bslmf::Tag<e_CHAR16_T> fromVal(char16_t& );
546 static bslmf::Tag<e_CHAR32_T> fromVal(char32_t& );
547#endif
548 /// Return a tag type representing the argument type. These functions
549 /// are declared but not defined and are intended to be used in an
550 /// unevaluated context (e.g., within `sizeof`) to convert an expression
551 /// into a compile-time enumeration constant.
552 static bslmf::Tag<e_SHORT> fromVal(short& );
553 static bslmf::Tag<e_USHORT> fromVal(unsigned short& );
554 static bslmf::Tag<e_INT> fromVal(int& );
555 static bslmf::Tag<e_UNSIGNED> fromVal(unsigned& );
556 static bslmf::Tag<e_LONG> fromVal(long& );
557 static bslmf::Tag<e_ULONG> fromVal(unsigned long& );
558 static bslmf::Tag<e_LONG_LONG> fromVal(long long& );
559 static bslmf::Tag<e_ULONG_LONG> fromVal(unsigned long long& );
560 static bslmf::Tag<e_FLOAT> fromVal(float& );
561 static bslmf::Tag<e_DOUBLE> fromVal(double& );
562 static bslmf::Tag<e_LONG_DOUBLE> fromVal(long double& );
563 static bslmf::Tag<e_VOIDPTR> fromVal(void *& );
564 static bslmf::Tag<e_CONST_VOIDPTR> fromVal(const void *& );
565 static bslmf::Tag<e_VOLATILE_VOIDPTR> fromVal(volatile void *& );
566 static bslmf::Tag<e_CONST_VOLATILE_VOIDPTR> fromVal(const volatile void*&);
568 template <class t_TP>
569 static bslmf::Tag<e_POINTER> fromVal(t_TP *&);
570 template <class t_TP>
571 static bslmf::Tag<e_OTHER> fromVal(t_TP&);
572};
573
574/// Metafunction to convert a type index back to a type. For each
575/// specialization of this struct, the `type` member will be the type
576/// corresponding to `index`. For example, if `index` is `e_UCHAR`, then
577/// `InvokeResult_Type<index>::type` is `unsigned char`.
578template <int t_INDEX> struct InvokeResult_Type;
579
580// Turn off bde_verify warnings for "Declaration without tag". Pedantically,
581// every 'type' declared in a metafunction should have the tag '// TYPES', but
582// that breaks up the clean 3-line declaration of each specialization, making
583// the pattern harder to for the eye to follow.
584// BDE_VERIFY pragma: push
585// BDE_VERIFY pragma: -KS00
586template <>
587struct InvokeResult_Type<InvokeResult_Index::e_VOID>
588 { typedef void type; };
589template <>
590struct InvokeResult_Type<InvokeResult_Index::e_BOOL>
591 { typedef bool type; };
592template <>
593struct InvokeResult_Type<InvokeResult_Index::e_CHAR>
594 { typedef char type; };
595template <>
596struct InvokeResult_Type<InvokeResult_Index::e_SCHAR>
597 { typedef signed char type; };
598template <>
599struct InvokeResult_Type<InvokeResult_Index::e_UCHAR>
600 { typedef unsigned char type; };
601#ifdef BSLS_COMPILERFEATURES_SUPPORT_UTF8_CHAR_TYPE
602template <>
603struct InvokeResult_Type<InvokeResult_Index::e_CHAR8_T>
604 { typedef char8_t type; };
605#endif
606template <>
607struct InvokeResult_Type<InvokeResult_Index::e_WCHAR_T>
608 { typedef wchar_t type; };
609#ifdef BSLS_COMPILERFEATURES_SUPPORT_UNICODE_CHAR_TYPES
610template <>
611struct InvokeResult_Type<InvokeResult_Index::e_CHAR16_T>
612 { typedef char16_t type; };
613template <>
614struct InvokeResult_Type<InvokeResult_Index::e_CHAR32_T>
615 { typedef char32_t type; };
616#endif
617template <>
618struct InvokeResult_Type<InvokeResult_Index::e_SHORT>
619 { typedef short type; };
620template <>
621struct InvokeResult_Type<InvokeResult_Index::e_USHORT>
622 { typedef unsigned short type; };
623template <>
624struct InvokeResult_Type<InvokeResult_Index::e_INT>
625 { typedef int type; };
626template <>
627struct InvokeResult_Type<InvokeResult_Index::e_UNSIGNED>
628 { typedef unsigned type; };
629template <>
630struct InvokeResult_Type<InvokeResult_Index::e_LONG>
631 { typedef long type; };
632template <>
633struct InvokeResult_Type<InvokeResult_Index::e_ULONG>
634 { typedef unsigned long type; };
635template <>
636struct InvokeResult_Type<InvokeResult_Index::e_LONG_LONG>
637 { typedef long long type; };
638template <>
639struct InvokeResult_Type<InvokeResult_Index::e_ULONG_LONG>
640 { typedef unsigned long long type; };
641template <>
642struct InvokeResult_Type<InvokeResult_Index::e_FLOAT>
643 { typedef float type; };
644template <>
645struct InvokeResult_Type<InvokeResult_Index::e_DOUBLE>
646 { typedef double type; };
647template <>
648struct InvokeResult_Type<InvokeResult_Index::e_LONG_DOUBLE>
649 { typedef long double type; };
650template <>
651struct InvokeResult_Type<InvokeResult_Index::e_VOIDPTR>
652 { typedef void *type; };
653template <>
654struct InvokeResult_Type<InvokeResult_Index::e_CONST_VOIDPTR>
655 { typedef const void *type; };
656template <>
657struct InvokeResult_Type<InvokeResult_Index::e_VOLATILE_VOIDPTR>
658 { typedef volatile void *type; };
659template <>
660struct InvokeResult_Type<InvokeResult_Index::e_CONST_VOLATILE_VOIDPTR>
661 { typedef const volatile void *type; };
662template <>
663struct InvokeResult_Type<InvokeResult_Index::e_NULLPTR_T>
664 { typedef bsl::nullptr_t type; };
665template <>
666struct InvokeResult_Type<InvokeResult_Index::e_POINTER>
667 { typedef void *type; };
668template <>
669struct InvokeResult_Type<InvokeResult_Index::e_OTHER>
670 { typedef InvokeResultDeductionFailed type; };
671// Re-enable warnings for "Declaration without tag"
672// BDE_VERIFY pragma: pop
673
674/// Utility metaprogramming functions inherited by other metaprogramming
675/// classes.
676struct InvokeResult_ImpUtils
677{
678
679 // TYPES
680
681 /// Type convertible from any lvalue type. Used for overload resolution
682 /// in metafunctions.
683 ///
684 /// See @ref bslmf_invokeresult
685 struct AnyLvalue {
686
687 // CREATORS
688
689 /// (Declared but not defined) Convert from any lvalue argument.
690 template <class t_TP>
691 AnyLvalue(volatile t_TP&);
692 };
693
694 /// Type convertible from any rvalue type. Used for overload resolution
695 /// in metafunctions.
696 ///
697 /// See @ref bslmf_invokeresult
698 struct AnyRvalue {
699
700 // CREATORS
701#ifdef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
702 /// (Declared but not defined) Convert from any rvalue argument.
703 template <class t_TP>
704 AnyRvalue(
705 t_TP&&,
707 int>::type = 0);
708#else
709 template <class t_TP>
711 // (Declared but not defined) Convert from any rvalue argument.
712 // This constructor will also match lvalue arguments, but is used
713 // in a context where 'AnyLValue' is a better conversion path.
714#endif
715 };
716
717 // CLASS METHODS
718#ifdef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
719 /// Return a reference to the specified `t_SOME_TYPE` template parameter
720 /// type; if `t_SOME_TYPE` is an rvalue, then the returned reference is
721 /// an rvalue reference. This function is declared but not defined and
722 /// is intended to be called in an unevaluated context. Because there
723 /// is no definition, the available constructors for `t_SOME_TYPE` are
724 /// irrelevant.
725 template <class t_SOME_TYPE>
726 static typename bsl::add_rvalue_reference<t_SOME_TYPE>::type myDeclval();
727#else
728 template <class t_SOME_TYPE>
729 static t_SOME_TYPE myDeclval();
730 // Return an object of the specified 't_SOME_TYPE' template parameter
731 // type. This function is declared but not defined and is intended to
732 // be called in an unevaluated context. Because there is no
733 // definition, the available constructors for 't_SOME_TYPE' are
734 // irrelevant.
735#endif
736
737 /// (Declared but not defined) Return `bslmf::Tag<false>()` if the
738 /// first argument is an rvalue and `bslmf::Tag<true>()` if it is
739 /// lvalue. In actual use, the second argument is always a literal
740 /// `int`, which causes the second overload to be preferred in case of
741 /// ambiguity.
742 static bslmf::Tag<false> checkLvalue(AnyRvalue, ...);
743 static bslmf::Tag<true > checkLvalue(AnyLvalue, int);
744
745 /// (Declared but not defined) Return `bslmf::Tag<true>()` if the
746 /// argument is `const`-qualified and `bslmf::Tag<false>()` otherwise.
747 template <class t_TP>
748 static bslmf::Tag<false> checkConst(t_TP&);
749 template <class t_TP>
750 static bslmf::Tag<true> checkConst(const t_TP&);
751
752 /// (Declared but not defined) Return `bslmf::Tag<true>()` if the
753 /// argument is `volatile`-qualified and `bslmf::Tag<false>()` otherwise.
754 ///
755 /// \note Note that if `t_TP` is both const- and
756 /// volatile-qualified, it will not match `volatile t_TP&`, hence the
757 /// need for the const overloads.
758 template <class t_TP>
759 static bslmf::Tag<false> checkVolatile(t_TP&);
760 template <class t_TP>
761 static bslmf::Tag<false> checkVolatile(const t_TP&);
762 template <class t_TP>
763 static bslmf::Tag<true> checkVolatile(volatile t_TP&);
764 template <class t_TP>
765 static bslmf::Tag<true> checkVolatile(const volatile t_TP&);
766
767 /// (Declared but not defined) Return the argument, with cv-qualifiers
768 /// removed.
769 template <class t_TP>
770 static t_TP& uncv(const t_TP&);
771 template <class t_TP>
772 static t_TP& uncv(const volatile t_TP&);
773
774 /// If the argument type `t_TP` is pointer to type `X`, where `X` is not
775 /// cv-`void`, return a reference to `X`; otherwise return a reference to `t_TP`.
776 ///
777 /// \note Note that these functions are declared but not defined
778 /// and are intended to be called only in an unevaluated context.
779 template <class t_TP>
780 static t_TP& unpoint(t_TP&);
781 template <class t_TP>
782 static const t_TP& unpoint(const t_TP&);
783 template <class t_TP>
784 static typename bsl::enable_if<!bsl::is_void<t_TP>::value, t_TP>::type&
785 unpoint(t_TP *&);
786 template <class t_TP>
787 static typename bsl::enable_if<!bsl::is_void<t_TP>::value, t_TP>::type&
788 unpoint(t_TP *const&);
789 template <class t_TP>
790 static typename bsl::enable_if<!bsl::is_void<t_TP>::value, t_TP>::type&
791 unpoint(t_TP *volatile&);
792 template <class t_TP>
793 static typename bsl::enable_if<!bsl::is_void<t_TP>::value, t_TP>::type&
794 unpoint(t_TP *const volatile&);
795};
796
797/// Starting with type, `t_UNQUAL_TYPE`, generate a new type by applying the
798/// following steps in order:
799///
800/// 1. If the specified `t_IS_CONST` parameter is true, apply
801/// `bsl::add_const`; otherwise leave unchanged.
802/// 2. If the specified `t_IS_VOLATILE` parameter is true, apply
803/// `bsl::add_volatile`; otherwise leave unchanged.
804/// 3. If the specified `t_IS_LVALUE` parameter is true, apply
805/// `bsl::add_lvalue_reference`; otherwise leave unchanged.
806///
807/// Set the `type` member to the resulting type.
808///
809/// See @ref bslmf_invokeresult
810template <class t_UNQUAL_TYPE,
811 bool t_IS_CONST,
812 bool t_IS_VOLATILE,
813 bool t_IS_LVALUE>
814struct InvokeResult_AddCVRef {
815
816 private:
817 // PRIVATE TYPES
818 typedef
819 typename bsl::conditional<t_IS_CONST,
821 t_UNQUAL_TYPE>::type CQualType;
822
823 typedef
824 typename bsl::conditional<t_IS_VOLATILE,
826 CQualType>::type CVQualType;
827
828 public:
829 // TYPES
830 typedef typename bsl::conditional<
831 t_IS_LVALUE,
833 CVQualType>::type type;
834};
835
836#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES // $var-args=13
837
838#ifndef BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS
839template <bool /* IS_VOID */, class t_FN, class... t_ARGTYPES>
840struct InvokeResult_FunctorDeduction : InvokeResult_ImpUtils {
841 // Deduce return type of 't_FN(t_ARGTYPES...)'. This template is
842 // instantiated only when 't_FN' is of class type (i.e., a functor). This
843 // primary template is selected when 't_FN(t_ARGTYPES...)' is not 'void'.
844 // Note that this template is not defined in C++11 mode (if 'decltype'
845 // exists).
846
847 typedef typename bsl::decay<t_FN>::type F;
848 // Remove references and cv-qualifiers from 't_FN', and decay function
849 // types and array types to pointers.
850
851 enum {
852 // In an unevaluated context ('BSLMF_TAG_TO_INT'), "invoke"
853 // 'myDeclval<t_FN>()(myDeclval<t_ARGTYPES>()...)' and use overloading
854 // to deduce the type and other attributes of the return value.
855
856 k_INDEX = BSLMF_TAG_TO_INT(InvokeResult_Index::fromVal(
857 uncv(myDeclval<t_FN>()(myDeclval<t_ARGTYPES>()...)))),
858 k_IS_POINTER = (k_INDEX == InvokeResult_Index::e_POINTER),
859 k_IS_LVALUE = BSLMF_TAG_TO_INT(
860 checkLvalue(myDeclval<t_FN>()(myDeclval<t_ARGTYPES>()...), 0)),
861 k_IS_CONST_PTR = k_IS_POINTER &&
862 BSLMF_TAG_TO_INT(checkConst(
863 myDeclval<t_FN>()(myDeclval<t_ARGTYPES>()...))),
864 k_IS_VOLATILE_PTR = k_IS_POINTER &&
865 BSLMF_TAG_TO_INT(checkVolatile(myDeclval<t_FN>()(
866 myDeclval<t_ARGTYPES>()...))),
867 k_TARGET_INDEX = BSLMF_TAG_TO_INT(InvokeResult_Index::fromVal(
868 uncv(unpoint(myDeclval<t_FN>()(myDeclval<t_ARGTYPES>()...))))),
869 k_IS_CONST_TARGET = BSLMF_TAG_TO_INT(checkConst(
870 unpoint(myDeclval<t_FN>()(myDeclval<t_ARGTYPES>()...)))),
871 k_IS_VOLATILE_TARGET = BSLMF_TAG_TO_INT(checkVolatile(
872 unpoint(myDeclval<t_FN>()(myDeclval<t_ARGTYPES>()...)))),
873 k_CANT_DEDUCE_TYPE = (k_TARGET_INDEX ==
874 (int)InvokeResult_Index::e_OTHER)
875 };
876
877 typedef typename bsl::conditional<
878 ! k_CANT_DEDUCE_TYPE,
879 typename InvokeResult_Type<k_TARGET_INDEX>::type,
881 >::type UnqualTargetType;
882 // The deduced result after stripping off pointer, reference, and
883 // cv-qualifiers. The 'TARGET_INDEX' indicates the fundamental type of
884 // the target result. If the target could not be deduced (i.e.,
885 // 'TARGET_INDEX == e_OTHER), then attempt to find the result by
886 // looking for a 'result_type' or 'ResultType' alias in 't_FN'; failing
887 // that, use 'InvokeResultDeductionFailed'.
888
889 typedef typename
890 InvokeResult_AddCVRef<UnqualTargetType,
891 static_cast<bool>(k_IS_CONST_TARGET)
892 && ! static_cast<bool>(k_CANT_DEDUCE_TYPE),
893 static_cast<bool>(k_IS_VOLATILE_TARGET)
894 && ! static_cast<bool>(k_CANT_DEDUCE_TYPE),
895 false>::type CVQualTargetType;
896 // The deduced target after adding back previously-stripped cv
897 // qualifiers, if any. Note that if the expression yielded a pointer
898 // type, these cv qualifiers apply to the target of the pointer, not
899 // the pointer itself.
900
901 typedef typename
903 && ! static_cast<bool>(k_CANT_DEDUCE_TYPE),
905 CVQualTargetType>::type UnqualType;
906 // The deduced result after adding back previously-stripped pointers,
907 // if any.
908
909 typedef typename
910 InvokeResult_AddCVRef<
911 UnqualType,
912 static_cast<bool>(k_IS_CONST_PTR)
913 && ! static_cast<bool>(k_CANT_DEDUCE_TYPE),
914 static_cast<bool>(k_IS_VOLATILE_PTR)
915 && ! static_cast<bool>(k_CANT_DEDUCE_TYPE),
916 static_cast<bool>(k_IS_LVALUE)
917 && ! static_cast<bool>(k_CANT_DEDUCE_TYPE)>::type Qtype;
918 // The deduced result after adding back previously-stripped cv
919 // qualifiers and references. Note that if the result is a pointer,
920 // the cv qualifiers apply to the pointer, not to the target.
921
922 typedef typename bsl::conditional<static_cast<bool>(k_IS_LVALUE), Qtype,
923 typename bsl::remove_cv<Qtype>::type>::type type;
924 // The final deduced result type. If the type is not a reference,
925 // top-level cv qualifiers are stripped off.
926};
927
928template <class t_FN, class... t_ARGTYPES>
929struct InvokeResult_FunctorDeduction<true /* IS_VOID */, t_FN, t_ARGTYPES...> {
930 // Deduce return type of 't_FN(t_ARGTYPES...)'. This template is
931 // instantiated only when 't_FN' is of class type (i.e., a functor). This
932 // specialization is selected when 't_FN(t_ARGTYPES...)' is cv-'void'.
933
934 typedef void type;
935};
936#endif // !BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS
937
938#endif
939
940/// This metafunction determines which cv qualifiers and reference
941/// qualifiers should be propagated from the first argument of
942/// @ref invoke_result . This primary template is instantiated when
943/// `t_ARG_TYPE` is the same or is derived from `t_MEMOF_CLASS`. The
944/// constant `k_IS_LVALUE` is true iff `t_ARG_TYPE` is an lvalue reference;
945/// the constant `k_IS_CONST` is true iff `t_ARG_TYPE` is const-qualified;
946/// and the constant `k_IS_VOLATILE` is true iff `t_ARG_TYPE` is
947/// volatile-qualified.
948///
949/// See @ref bslmf_invokeresult
950template <class t_MEMOF_CLASS,
951 class t_ARG_TYPE,
952 bool t_IS_DERIVED = bsl::is_convertible<
954 typename bsl::decay<t_MEMOF_CLASS>::type *>::value>
955struct InvokeResult_MemPtrArgQualifiers {
956
957 // TYPES
958 enum {
960 k_IS_CONST = bsl::is_const<
962 k_IS_VOLATILE = bsl::is_volatile<
964 };
965};
966
967/// This metafunction determines which cv qualifiers and reference
968/// qualifiers should be propagated from the first argument of
969/// @ref invoke_result .
970///
971/// This specialization is instantiated when `t_ARG_TYPE` is not derived
972/// from `t_MEMOF_CLASS` and is assumed to be a pointer or smart pointer
973/// type. If type `A` is the result of dereferencing an object of type
974/// `t_ARG_TYPE`, then the constant `k_IS_LVALUE` is true iff `A` is an
975/// lvalue reference; the constant `k_IS_CONST` is true iff `A` is a
976/// const-qualified reference; and the constant `k_IS_VOLATILE` is true iff
977/// `A` is a volatile-qualified reference.
978template <class t_MEMOF_CLASS, class t_ARG_TYPE>
979struct InvokeResult_MemPtrArgQualifiers<t_MEMOF_CLASS, t_ARG_TYPE, false>
980: InvokeResult_ImpUtils {
981
982#ifdef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
983 private:
984 // CLASS METHODS
985
986 /// (Declared but not defined.) Return an lvalue reference
987 /// corresponding of the specified `t_TP` type, which is deduced from
988 /// the specified unnamed argument. If the argument is an lvalue, the
989 /// return type is identical to the argument type. If the argument is
990 /// an rvalue, the return type is an lvalue to the argument type with
991 /// the same cv qualifiers. This function is useful for avoiding too
992 /// many redundant overloads in metafunctions that determine cv
993 /// qualifications, etc.
994 template <class t_TP>
995 static t_TP& tolvalue(t_TP&&);
996
997 public:
998 // TYPES
999 enum {k_IS_LVALUE = BSLMF_TAG_TO_INT(checkLvalue(*myDeclval<t_ARG_TYPE>(),
1000 0)),
1001 k_IS_CONST =
1002 BSLMF_TAG_TO_INT(checkConst(tolvalue(*myDeclval<t_ARG_TYPE>()))),
1003 k_IS_VOLATILE = BSLMF_TAG_TO_INT(
1004 checkVolatile(tolvalue(*myDeclval<t_ARG_TYPE>())))};
1005#else
1006 public:
1007 // TYPES
1008 enum {
1009 k_IS_LVALUE = BSLMF_TAG_TO_INT(checkLvalue(*myDeclval<t_ARG_TYPE>(),
1010 0)),
1011 // In C++03, cv qualifiers are discarded from rvalues.
1012 k_IS_CONST = k_IS_LVALUE &&
1013 BSLMF_TAG_TO_INT(checkConst(*myDeclval<t_ARG_TYPE>())),
1014 k_IS_VOLATILE = k_IS_LVALUE && BSLMF_TAG_TO_INT(checkVolatile(
1015 *myDeclval<t_ARG_TYPE>()))
1016 };
1017#endif // BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
1018};
1019
1020#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES // $var-args=13
1021
1022/// Forward declaration
1023template <class t_VOID_TYPE, class t_FN, class... t_ARGTYPES>
1024struct InvokeResult_FunctorImp;
1025
1026/// Forward declaration
1027template <class t_VOID_TYPE, class t_FN, class... t_ARGTYPES>
1028struct InvokeResult_FuncPtrImp;
1029
1030/// Forward declaration
1031template <class t_FN, class... t_ARGTYPES>
1032struct InvokeResult_MemFuncPtrImp;
1033
1034/// Forward declaration
1035template <class t_FN, class... t_ARGTYPES>
1036struct InvokeResult_MemObjPtrImp;
1037
1038 // ================================
1039 // struct template InvokeResult_Imp
1040 // ================================
1041
1042/// This component-private, partial `struct` template specialization
1043/// provides the implementation of `InvokeResult_Imp` for types that are
1044/// neither function pointers, pointers to member functions, nor pointers to
1045/// member objects.
1046template <bool t_IS_FUNCPTR,
1047 bool t_IS_MEMFUNCPTR,
1048 bool t_IS_MEMOBJPTR,
1049 class t_FN,
1050 class... t_ARGTYPES>
1051struct InvokeResult_Imp : InvokeResult_FunctorImp<void, t_FN, t_ARGTYPES...> {
1052};
1053
1054/// This component-private, partial `struct` template specialization
1055/// provides the implementation of `InvokeResult_Imp` for function pointer
1056/// types.
1057template <class t_FN, class... t_ARGTYPES>
1058struct InvokeResult_Imp<true /* t_IS_FUNCPTR */,
1059 false,
1060 false,
1061 t_FN,
1062 t_ARGTYPES...>
1063: InvokeResult_FuncPtrImp<void, t_FN, t_ARGTYPES...> {
1064};
1065
1066/// This component-private, partial `struct` template specialization
1067/// provides the implementation of `InvokeResult_Imp` for pointer to member
1068/// function types.
1069template <class t_FN, class... t_ARGTYPES>
1070struct InvokeResult_Imp<false,
1071 true /* t_IS_MEMFUNCPTR */,
1072 false,
1073 t_FN,
1074 t_ARGTYPES...>
1075: InvokeResult_MemFuncPtrImp<t_FN, t_ARGTYPES...> {
1076};
1077
1078/// This component-private, partial `struct` template specialization
1079/// provides the implementation of `InvokeResult_Imp` for pointer to member
1080/// object types.
1081template <class t_FN, class... t_ARGTYPES>
1082struct InvokeResult_Imp<false,
1083 false,
1084 true /* t_IS_MEMOBJPTR */,
1085 t_FN,
1086 t_ARGTYPES...>
1087: InvokeResult_MemObjPtrImp<t_FN, t_ARGTYPES...> {
1088};
1089
1090 // =======================================
1091 // struct template InvokeResult_FunctorImp
1092 // =======================================
1093
1094#ifdef BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS
1095/// Implementation of `invoke_result<t_FN, t_ARGTYPES...>`. This
1096/// specialization is instantiated in C++11 and later when `t_FN` is neither
1097/// a pointer-to-function, pointer-to-member-function, nor
1098/// pointer-to-member-object type, and the `INVOKE(fn, args...)` expression,
1099/// is *not* well-formed given `fn` is an object of the specified `t_FN`
1100/// type and `args...` are objects of the specified `t_ARGTYPES...` types.
1101/// The `INVOKE(fn, args...)` expression in this case is `fn(args...)`.
1102///
1103/// \note Note that this `struct` does not provide a `type` typedef.
1104///
1105/// See @ref bslmf_invokeresult
1106template <class t_VOID_TYPE, class t_FN, class... t_ARGTYPES>
1107struct InvokeResult_FunctorImp {
1108};
1109
1110/// Implementation of `invoke_result<t_FN, t_ARGTYPES...>`. This
1111/// specialization is instantiated in C++11 and later when `t_FN` is neither
1112/// a pointer-to-function, pointer-to-member-function, nor
1113/// pointer-to-member-object type, and the `INVOKE(fn, args...)` expression
1114/// is well-formed given `fn` is an object of the specified `t_FN` type and
1115/// `args...` are objects of the specified `t_ARGTYPES...` types. The
1116/// `INVOKE(fn, args...)` expression in this case is `fn(args...)`.
1117template <class t_FN, class... t_ARGTYPES>
1118struct InvokeResult_FunctorImp<
1119 typename bslmf::VoidType<decltype(InvokeResult_ImpUtils::myDeclval<t_FN>()(
1120 InvokeResult_ImpUtils::myDeclval<t_ARGTYPES>()...))>::type,
1121 t_FN,
1122 t_ARGTYPES...> : InvokeResult_ImpUtils {
1123
1124 // TYPES
1125
1126 /// For C++11 and later, the type of the `INVOKE(fn, args...)`
1127 /// expression given `fn` is an object of the specified `t_FN` type and
1128 /// `args...` are objects of the specified `t_ARGTYPES...` types. The
1129 /// `INVOKE(fn, args...)` expression in this case is `fn(args...)`.
1130 typedef decltype(myDeclval<t_FN>()(myDeclval<t_ARGTYPES>()...)) type;
1131};
1132#else // ! BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS
1133template <class t_VOID_TYPE, class t_FN, class... t_ARGTYPES>
1134struct InvokeResult_FunctorImp : InvokeResult_ImpUtils {
1135 // Implementation of 'invoke_result<t_FN, t_ARGTYPES...>'. This
1136 // specialization is instantiated in C++03 when 't_FN' is neither a
1137 // pointer-to-function, pointer-to-member-function, nor
1138 // pointer-to-member-object type.
1139
1140 // TYPES
1141 enum {
1142 // Determine if 'myDeclval<t_FN>()(myDeclval<t_ARGTYPES>()...)' is a
1143 // void expression by invoking the overloaded comma operator using a
1144 // 'InvokeResult_VoidChecker' as the second argument. If the
1145 // expression is of void type, then the built-in comma operator will
1146 // yield 'InvokeResult_VoidChecker', otherwise the overloaded comma
1147 // operator will yield 'bslmf::Tag<false>'
1148 k_IS_VOID = BSLMF_TAG_TO_INT((
1149 myDeclval<t_FN>()(myDeclval<t_ARGTYPES>()...),
1150 InvokeResult_VoidChecker()))
1151 };
1152
1153 typedef typename InvokeResult_FunctorDeduction<k_IS_VOID,
1154 t_FN,
1155 t_ARGTYPES...>::type type;
1156 // For C++03, the result of invoking
1157 // 'myDeclval<t_FN>()(myDeclval<t_ARGTYPES>()...)' if it can be deduced
1158 // without 'decltype'; otherwise 'InvokeResultDeductionFailed'.
1159};
1160#endif // BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS
1161
1162 // =======================================
1163 // struct template InvokeResult_FuncPtrImp
1164 // =======================================
1165
1166#ifdef BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS
1167/// Implementation of `invoke_result<t_FN, t_ARGTYPES...>`. This
1168/// specialization is instantiated in C++11 and later when `t_FN` is a
1169/// pointer-to-function type, and the `INVOKE(fn, args...)` expression is
1170/// *not* well-formed given `fn` is an object of the specified `t_FN` type
1171/// and `args...` are objects of the specified `t_ARGTYPES...` types. The
1172/// `INVOKE(fn, args...)` expression in this case is `fn(args...)`.
1173///
1174/// \note Note that this `struct` does not provide a `type` typedef.
1175///
1176/// See @ref bslmf_invokeresult
1177template <class t_VOID_TYPE, class t_FN, class... t_ARGTYPES>
1178struct InvokeResult_FuncPtrImp {
1179};
1180
1181/// Implementation of `invoke_result<t_FN, t_ARGTYPES...>`. This
1182/// specialization is instantiated in C++11 and later when `t_FN` is a
1183/// pointer-to-function type, and the `INVOKE(fn, args...)` expression is
1184/// well-formed given `fn` is an object of the specified `t_FN` type and
1185/// `args...` are objects of the specified `t_ARGTYPES...` types. The
1186/// `INVOKE(fn, args...)` expression in this case is `fn(args...)`.
1187template <class t_FN, class... t_ARGTYPES>
1188struct InvokeResult_FuncPtrImp<
1189 typename bslmf::VoidType<decltype(InvokeResult_ImpUtils::myDeclval<t_FN>()(
1190 InvokeResult_ImpUtils::myDeclval<t_ARGTYPES>()...))>::type,
1191 t_FN,
1192 t_ARGTYPES...> : InvokeResult_ImpUtils {
1193
1194 // TYPES
1195
1196 /// For C++11 and later, the type of result of the `INVOKE(fn, args...)`
1197 /// expression where `fn` is an object of the specified `t_FN` type, and
1198 /// `args...` are objects of the specified `t_ARGTYPES...` types. The
1199 /// `INVOKE(fn, args...)` expression in this case is is `fn(args...)`.
1200 ///
1201 /// See @ref bslmf_invokeresult
1202 typedef decltype(myDeclval<t_FN>()(myDeclval<t_ARGTYPES>()...)) type;
1203};
1204#else // ! BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS
1205template <class t_VOID_TYPE, class t_FN, class... t_ARGTYPES>
1206struct InvokeResult_FuncPtrImp {
1207 // Implementation of 'invoke_result<t_FN, t_ARGTYPES...>. This
1208 // specialization is instantiated in C++03 when 't_FN' is a
1209 // pointer-to-function type. Note that this C++03 implementation does not
1210 // check whether 't_ARGTYPES...' are valid for 't_FN'.
1211
1213 // The return value of the function pointed-to by 't_FN'.
1214
1215 typedef typename bsl::conditional<
1217 QType,
1218 typename bsl::remove_cv<QType>::type>::type type;
1219 // The return value of the function pointed-to by 't_FN'. If the type
1220 // is a scalar rvalue, cv qualifications are stripped off.
1221};
1222#endif // BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS
1223
1224 // ==========================================
1225 // struct template InvokeResult_MemFuncPtrImp
1226 // ==========================================
1227
1228#ifdef BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS
1229/// Forward declaration.
1230template <class t_VOID_TYPE,
1231 bool t_ARG1_DERIVES_FROM_CLASS,
1232 bool t_ARG1_IS_REFERENCE_WRAPPER,
1233 class t_FN,
1234 class t_ARG1TYPE,
1235 class... t_ARGTYPES>
1236struct InvokeResult_MemFuncPtrImpDispatch;
1237
1238// SPECIALIZATIONS
1239
1240/// Implementation of `invoke_result<t_FN, t_ARGTYPES...>`. This
1241/// specialization is instantiated in C++11 and later when `t_FN` is a
1242/// pointer-to-member-function type, and the `t_ARGTYPES...` pack is empty.
1243///
1244/// \note Note that this `struct` does not provide a `type` typedef.
1245template <class t_FN>
1246struct InvokeResult_MemFuncPtrImp<t_FN> {
1247};
1248
1249/// Implementation of `invoke_result<t_FN, t_ARGTYPES...>`. This
1250/// specialization is instantiated in C++11 and later when `t_FN` is a
1251/// pointer-to-member-function type, and the `t_ARGTYPES...` pack contains
1252/// 1 type or more.
1253template <class t_FN, class t_ARG1TYPE, class... t_ARGTYPES>
1254struct InvokeResult_MemFuncPtrImp<t_FN, t_ARG1TYPE, t_ARGTYPES...>
1255: InvokeResult_MemFuncPtrImpDispatch<
1256 void,
1257 IsAccessibleBaseOf<
1258 typename MemberFunctionPointerTraits<t_FN>::ClassType,
1259 typename bsl::remove_reference<t_ARG1TYPE>::type>::value,
1260 IsReferenceWrapper<typename bsl::remove_const<
1261 typename bsl::remove_reference<t_ARG1TYPE>::type>::type>::value,
1262 t_FN,
1263 t_ARG1TYPE,
1264 t_ARGTYPES...> {
1265};
1266#else // ! BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS
1267template <class t_FN, class... t_ARGTYPES>
1268struct InvokeResult_MemFuncPtrImp<t_FN, t_ARGTYPES...> {
1269 // Implementation of 'invoke_result<t_FN, t_ARGTYPES...>. This
1270 // specialization is instantiated in C++03 when 't_FN' is a
1271 // pointer-to-member-function type.
1272
1273 typedef typename MemberFunctionPointerTraits<t_FN>::ResultType QType;
1274 // The return value of the function pointed-to by 't_FN'.
1275
1276 typedef typename bsl::conditional<
1278 QType,
1279 typename bsl::remove_cv<QType>::type>::type type;
1280 // The return value of the function pointed-to by 't_FN'. If the type
1281 // is a scalar rvalue, cv qualifications are stripped off.
1282};
1283#endif // BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS
1284
1285 // ==================================================
1286 // struct template InvokeResult_MemFuncPtrImpDispatch
1287 // ==================================================
1288
1289#ifdef BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS
1290/// Implementation of `invoke_result<t_FN, t_ARG1TYPE, t_ARGTYPES...>`.
1291/// This specialization is instantiated in C++11 and later when `t_FN` is a
1292/// pointer-to-member-function type, and the `INVOKE(fn, arg1, args...)`
1293/// expression is *not* well-formed given `fn` is an object of the specified
1294/// `t_FN` type and `arg1, args...` are objects of the specified `t_ARG1TYPE, t_ARGTYPES...` types.
1295///
1296/// \note Note that this `struct` does not
1297/// provide a `type` typedef.
1298///
1299/// See @ref bslmf_invokeresult
1300template <class t_VOID_TYPE,
1301 bool t_ARG1_DERIVES_FROM_CLASS,
1302 bool t_ARG1_IS_REFERENCE_WRAPPER,
1303 class t_FN,
1304 class t_ARG1TYPE,
1305 class... t_ARGTYPES>
1306struct InvokeResult_MemFuncPtrImpDispatch {
1307};
1308
1309/// Implementation of `invoke_result<t_FN, t_ARG1TYPE, t_ARGTYPES...>`.
1310/// This specialization is instantiated in C++11 and later when `t_FN` is a
1311/// pointer-to-member-function type, `t_ARG1TYPE` is neither a class type
1312/// that derives from the class type of `t_FN` nor a specialization of
1313/// `bsl::reference_wrapper`, and the `INVOKE(fn, arg1, args...)` expression
1314/// is well-formed given `fn` is an object of the specified `t_FN` type and
1315/// `arg1, args...` are objects of the specified `t_ARG1TYPE, t_ARGTYPES...`
1316/// types. The `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 */ false,
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, 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 class type that
1344/// derives from the class type of `t_FN`, and the
1345/// `INVOKE(fn, arg1, args...)` expression is well-formed given `fn` is an
1346/// object of the specified `t_FN` type and `arg1, args...` are objects of
1347/// the specified `t_ARG1TYPE, t_ARGTYPES...` types. The
1348/// `INVOKE(fn, arg1, args...)` expression in this case is
1349/// `(arg1.*fn)(args...)`.
1350template <class t_FN, class t_ARG1TYPE, class... t_ARGTYPES>
1351struct InvokeResult_MemFuncPtrImpDispatch<
1352 typename bslmf::VoidType<
1353 decltype((InvokeResult_ImpUtils::myDeclval<t_ARG1TYPE>().*
1354 InvokeResult_ImpUtils::myDeclval<t_FN>())(
1355 InvokeResult_ImpUtils::myDeclval<t_ARGTYPES>()...))>::type,
1356 /* t_ARG1_DERIVES_FROM_CLASS */ true,
1357 /* t_ARG1_IS_REFERENCE_WRAPPER */ false,
1358 t_FN,
1359 t_ARG1TYPE,
1360 t_ARGTYPES...> : InvokeResult_ImpUtils {
1361
1362 // TYPES
1363
1364 /// For C++11 and later, the type of the `INVOKE(fn, arg1, args...)`
1365 /// expression where `fn` is an object of the specified `t_FN` type, and
1366 /// `arg1, args...` are objects of the specified
1367 /// `t_ARG1TYPE, t_ARGTYPES...` types. The `INVOKE(fn, arg1, args...)`
1368 /// expression in this case is `(arg1.*fn)(args...)`.
1369 typedef decltype((myDeclval<t_ARG1TYPE>().*
1370 myDeclval<t_FN>())(myDeclval<t_ARGTYPES>()...)) type;
1371};
1372
1373/// Implementation of `invoke_result<t_FN, t_ARGTYPES...>`. This
1374/// specialization is instantiated in C++11 and later when `t_FN` is a
1375/// pointer-to-member-function type, `t_ARG1TYPE` is a specialization of
1376/// `bsl::reference_wrapper`, and the `INVOKE(fn, arg1, args...)` expression
1377/// is well-formed given `fn` is an object of the specified `t_FN` type and
1378/// `arg1, args...` are objects of the specified `t_ARG1TYPE, t_ARGTYPES...`
1379/// types. The `INVOKE(fn, arg1, args...)` expression in this case is
1380/// `(arg1.get().*fn)(args...)`.
1381template <class t_FN, class t_ARG1TYPE, class... t_ARGTYPES>
1382struct InvokeResult_MemFuncPtrImpDispatch<
1383 typename bslmf::VoidType<
1384 decltype((InvokeResult_ImpUtils::myDeclval<t_ARG1TYPE>().get().*
1385 InvokeResult_ImpUtils::myDeclval<t_FN>())(
1386 InvokeResult_ImpUtils::myDeclval<t_ARGTYPES>()...))>::type,
1387 /* t_ARG1_DERIVES_FROM_CLASS */ false,
1388 /* t_ARG1_IS_REFERENCE_WRAPPER */ true,
1389 t_FN,
1390 t_ARG1TYPE,
1391 t_ARGTYPES...> : InvokeResult_ImpUtils {
1392
1393 // TYPES
1394
1395 /// For C++11 and later, the type of the `INVOKE(fn, arg1, args...)`
1396 /// expression where `fn` is an object of the specified `t_FN` type, and
1397 /// `arg1, args...` are objects of the specified
1398 /// `t_ARG1TYPE, t_ARGTYPES...` types. The `INVOKE(fn, arg1, args...)`
1399 /// expression in this case is `(arg1.get().*fn)(args...)`.
1400 typedef decltype((myDeclval<t_ARG1TYPE>().get().*
1401 myDeclval<t_FN>())(myDeclval<t_ARGTYPES>()...)) type;
1402};
1403
1404#endif // BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS
1405
1406 // =========================================
1407 // struct template InvokeResult_MemObjPtrImp
1408 // =========================================
1409
1410#ifdef BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS
1411/// Forward declaration.
1412template <class t_VOID_TYPE,
1413 bool t_ARG_DERIVES_FROM_CLASS,
1414 bool t_ARG_IS_REFERENCE_WRAPPER,
1415 class t_FN,
1416 class t_ARGTYPE>
1417struct InvokeResult_MemObjPtrImpDispatch;
1418
1419// SPECIALIZATIONS
1420
1421/// Implementation of `invoke_result<t_FN, t_ARGTYPES...>`. This
1422/// specialization is instantiated in C++11 and later when `t_FN` is a
1423/// pointer-to-member-object type, and the `t_ARGTYPES...` pack is empty or contains more than 1 type.
1424///
1425/// \note Note that this `struct` does not provide a
1426/// `type` typedef.
1427///
1428/// See @ref bslmf_invokeresult
1429template <class t_FN, class... t_ARGTYPES>
1430struct InvokeResult_MemObjPtrImp {
1431};
1432
1433/// Implementation of `invoke_result<t_FN, t_ARGTYPES...>`. This
1434/// specialization is instantiated in C++11 and later when `t_FN` is a
1435/// pointer-to-member-object type and the `t_ARGTYPES...` pack contains
1436/// exactly 1 type.
1437template <class t_FN, class t_ARGTYPE>
1438struct InvokeResult_MemObjPtrImp<t_FN, t_ARGTYPE>
1439: InvokeResult_MemObjPtrImpDispatch<
1440 void,
1441 IsAccessibleBaseOf<
1442 typename MemberPointerTraits<t_FN>::ClassType,
1443 typename bsl::remove_reference<t_ARGTYPE>::type>::value,
1444 IsReferenceWrapper<typename bsl::remove_const<
1445 typename bsl::remove_reference<t_ARGTYPE>::type>::type>::value,
1446 t_FN,
1447 t_ARGTYPE> {
1448};
1449
1450#else // ! BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS
1451
1452template <class t_FN, class... t_ARGTYPES>
1453struct InvokeResult_MemObjPtrImp {
1454};
1455
1456template <class t_CLASS, class t_RET, class t_ARGTYPE>
1457struct InvokeResult_MemObjPtrImp<t_RET t_CLASS::*, t_ARGTYPE> {
1458 // Implementation of 'invoke_result<t_FN, t_ARGTYPES...>. This
1459 // specialization is instantated in C++03 when 't_FN' is a pointer to data
1460 // member and 't_ARGTYPE' is an rvalue type.
1461
1462 private:
1463 typedef InvokeResult_MemPtrArgQualifiers<t_CLASS, t_ARGTYPE> ArgQualifiers;
1464 // Determine the cv qualifications and reference qualifications from
1465 // 't_ARGTYPE' that should be applied to 't_RET'.
1466
1467 typedef typename InvokeResult_AddCVRef<t_RET,
1468 ArgQualifiers::k_IS_CONST,
1469 ArgQualifiers::k_IS_VOLATILE,
1470 ArgQualifiers::k_IS_LVALUE>::type
1471 cvtype;
1472 // The type of member pointed to by the pointer-to-member-object, with
1473 // cv and reference qualifiers taken from 't_ARGTYPE'.
1474
1475 public:
1476#ifdef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
1477 typedef typename bsl::conditional<
1478 ArgQualifiers::k_IS_LVALUE,
1479 cvtype,
1480 typename bsl::add_rvalue_reference<cvtype>::type>::type type;
1481 // Result type. If rvalue references are supported, data members of
1482 // rvalues are always returned as rvalue references in C++11 and later.
1483#else
1484 typedef cvtype type;
1485 // Rvalue result type.
1486#endif
1487};
1488#endif // BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS
1489
1490 // =================================================
1491 // struct template InvokeResult_MemObjPtrImpDispatch
1492 // =================================================
1493
1494#ifdef BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS
1495/// Implementation of `invoke_result<t_FN, t_ARGTYPE>`. This specialization
1496/// is instantiated in C++11 and later when `t_FN` is a
1497/// pointer-to-member-object type, and the `INVOKE(fn, arg)` expression is
1498/// *not* well-formed given `fn` is an object of the specified `t_FN` type and `arg` is an object of the specified `t_ARGTYPE`.
1499///
1500/// \note Note that this
1501/// `struct` does not provide a `type` typedef.
1502///
1503/// See @ref bslmf_invokeresult
1504template <class t_VOID_TYPE,
1505 bool t_ARG_DERIVES_FROM_CLASS,
1506 bool t_ARG_IS_REFERENCE_WRAPPER,
1507 class t_FN,
1508 class t_ARGTYPE>
1509struct InvokeResult_MemObjPtrImpDispatch {
1510};
1511
1512/// Implementation of `invoke_result<t_FN, t_ARGTYPE>`. This specialization
1513/// is instantiated in C++11 and later when `t_FN` is a
1514/// pointer-to-member-object type, `t_ARGTYPE` is neither a class type that
1515/// derives from the class type of `t_FN` nor a specialization of
1516/// `bsl::reference_wrapper`, and the `INVOKE(fn, arg)` expression is
1517/// well-formed given `fn` is an object of the specified `t_FN` type and
1518/// `arg` is an object of the specified `t_ARGTYPE` type. The
1519/// `INVOKE(fn, arg)` expression in this case is `(*arg).*fn`.
1520template <class t_FN, class t_ARGTYPE>
1521struct InvokeResult_MemObjPtrImpDispatch<
1522 typename bslmf::VoidType<
1523 decltype((*InvokeResult_ImpUtils::myDeclval<t_ARGTYPE>()).*
1524 InvokeResult_ImpUtils::myDeclval<t_FN>())>::type,
1525 /* t_ARG1_DERIVES_FROM_CLASS */ false,
1526 /* t_ARG1_IS_REFERENCE_WRAPPER */ false,
1527 t_FN,
1528 t_ARGTYPE> : InvokeResult_ImpUtils {
1529
1530 // TYPES
1531 typedef decltype((*myDeclval<t_ARGTYPE>()).*myDeclval<t_FN>()) type;
1532 // For C++11 and later, the type of the 'INVOKE(fn, arg)' expression where
1533 // 'fn' is an object of the specified 't_FN' type, and 'arg' is an object
1534 // of the specified 't_ARGTYPE' type. The 'INVOKE(fn, arg)' expression in
1535 // this case is '(*arg).*fn'.
1536};
1537
1538/// Implementation of `invoke_result<t_FN, t_ARGTYPE>`. This specialization
1539/// is instantiated in C++11 and later when `t_FN` is a
1540/// pointer-to-member-object type, `t_ARGTYPE` is a class type that derives
1541/// from the class type of `t_FN`, and the `INVOKE(fn, arg)` expression is
1542/// well-formed given `fn` is an object of the specified `t_FN` type and
1543/// `arg` is an object of the specified `t_ARGTYPE` type. The
1544/// `INVOKE(fn, arg)` expression in this case is `arg1.*fn`.
1545template <class t_FN, class t_ARGTYPE>
1546struct InvokeResult_MemObjPtrImpDispatch<
1547 typename bslmf::VoidType<
1548 decltype(InvokeResult_ImpUtils::myDeclval<t_ARGTYPE>().*
1549 InvokeResult_ImpUtils::myDeclval<t_FN>())>::type,
1550 /* t_ARG_DERIVES_FROM_CLASS */ true,
1551 /* t_ARG_IS_REFERENCE_WRAPPER */ false,
1552 t_FN,
1553 t_ARGTYPE> : InvokeResult_ImpUtils {
1554
1555 // TYPES
1556 typedef decltype(myDeclval<t_ARGTYPE>().*myDeclval<t_FN>()) type;
1557 // For C++11 and later, the type of the 'INVOKE(fn, arg)' expression where
1558 // 'fn' is an object of the specified 't_FN' type, and 'arg' is an object
1559 // of the specified 't_ARGTYPE' type. The 'INVOKE(fn, arg)' expression in
1560 // this case is 'arg1.*fn'.
1561};
1562
1563/// Implementation of `invoke_result<t_FN, t_ARGTYPE>`. This specialization
1564/// is instantiated in C++11 and later when `t_FN` is a
1565/// pointer-to-member-object type, `t_ARGTYPE` is a specialization of
1566/// `bsl::reference_wrapper`, and the `INVOKE(fn, arg)` expression is
1567/// well-formed given `fn` is an object of the specified `t_FN` type and
1568/// `arg` is an object of the specified `t_ARGTYPE` type. The
1569/// `INVOKE(fn, arg)` expression in this case is `arg.get().*fn`.
1570template <class t_FN, class t_ARGTYPE>
1571struct InvokeResult_MemObjPtrImpDispatch<
1572 typename bslmf::VoidType<
1573 decltype(InvokeResult_ImpUtils::myDeclval<t_ARGTYPE>().get().*
1574 InvokeResult_ImpUtils::myDeclval<t_FN>())>::type,
1575 /* t_ARG1_DERIVES_FROM_CLASS */ false,
1576 /* t_ARG1_IS_REFERENCE_WRAPPER */ true,
1577 t_FN,
1578 t_ARGTYPE> : InvokeResult_ImpUtils {
1579
1580 // TYPES
1581 typedef decltype(myDeclval<t_ARGTYPE>().get().*myDeclval<t_FN>()) type;
1582 // For C++11 and later, the type of the 'INVOKE(fn, arg)' expression where
1583 // 'fn' is an object of the specified 't_FN' type, and 'arg' is an object
1584 // of the specified 't_ARGTYPE' type. The 'INVOKE(fn, arg)' expression in
1585 // this case is 'arg.get().*fn'.
1586};
1587
1588#endif // BSLMF_INVOKERESULT_SUPPORT_CPP17_SEMANTICS
1589
1590#endif
1591
1592} // close package namespace
1593
1594
1595#endif // End C++11 code
1596
1597#endif // ! defined(INCLUDED_BSLMF_INVOKERESULT)
1598
1599// ----------------------------------------------------------------------------
1600// Copyright 2018 Bloomberg Finance L.P.
1601//
1602// Licensed under the Apache License, Version 2.0 (the "License");
1603// you may not use this file except in compliance with the License.
1604// You may obtain a copy of the License at
1605//
1606// http://www.apache.org/licenses/LICENSE-2.0
1607//
1608// Unless required by applicable law or agreed to in writing, software
1609// distributed under the License is distributed on an "AS IS" BASIS,
1610// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1611// See the License for the specific language governing permissions and
1612// limitations under the License.
1613// ----------------------------- END-OF-FILE ----------------------------------
1614
1615/** @} */
1616/** @} */
1617/** @} */
decay_imp< U, k_ISARRAY, k_ISFUNC >::type type
Definition bslmf_decay.h:167
Definition bslmf_invokeresult.h:362
#define BSLMF_TAG_TO_INT(BSLMF_EXPR)
Definition bslmf_tag.h:179
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition bdlat_valuetypefunctions.h:939
BloombergLP::bsls::Nullptr_Impl::Type nullptr_t
Definition bsls_nullptr.h:283
Definition bdlbb_blob.h:579
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:176
t_TYPE & type
This typedef defines the return type of this meta function.
Definition bslmf_addlvaluereference.h:131
BloombergLP::bslmf::AddPointer_Impl< t_TYPE >::type type
Definition bslmf_addpointer.h:181
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:178
Definition bslmf_conditional.h:123
Definition bslmf_enableif.h:530
Definition bslmf_integralconstant.h:261
Definition bslmf_isclass.h:164
Definition bslmf_isconst.h:145
Definition bslmf_isconvertible.h:875
Definition bslmf_islvaluereference.h:135
Definition bslmf_ismemberobjectpointer.h:141
Definition bslmf_isreference.h:137
Definition bslmf_isrvaluereference.h:126
Definition bslmf_isvolatile.h:145
remove_const< typenameremove_volatile< t_TYPE >::type >::type type
Definition bslmf_removecv.h:128
t_TYPE type
This typedef is an alias to the (template parameter) t_TYPE.
Definition bslmf_removereference.h:156
Definition bslmf_functionpointertraits.h:147
Definition bslmf_invokeresult.h:312
InvokeResultDeductionFailed(const t_TYPE &)
Definition bslmf_invokeresult.h:319
Forward declaration.
Definition bslmf_invokeresult.h:419
BloombergLP::bslmf::InvokeResult_Imp< k_IS_FUNCPTR, k_IS_MEMFUNCPTR, k_IS_MEMOBJPTR, FwdFn, t_ARGTYPES... > BaseType
Definition bslmf_invokeresult.h:460
Definition bslmf_invokeresult.h:685
AnyLvalue(volatile t_TP &)
(Declared but not defined) Convert from any lvalue argument.
Definition bslmf_invokeresult.h:698
t_FALLBACK type
Definition bslmf_resulttype.h:262
Definition bslmf_tag.h:166