namespace eggs { // invoke template <class F, class... Args> constexpr invoke_result_t<F, Args...> invoke(F&& f, Args&&... Args) noexcept(is_nothrow_invocable_v<F, Args...>); // invoke_r template <class R, class F, class... Args> // (extension) constexpr R INVOKE(F&& f, Args&&... args) noexcept(is_nothrow_invocable_r_v<R, F, Args...>); // invoke_result template <class Fn, class... ArgTypes> struct invoke_result; template <class Fn, class... ArgTypes> using invoke_result_t = typename invoke_result<Fn, ArgTypes...>::type; // is_invocable template <class Fn, class... ArgTypes> struct is_invocable; template <class Fn, class... ArgTypes> // (C++14) inline constexpr bool is_invocable_v = is_invocable<Fn, ArgTypes...>::value; // is_invocable_r template <class R, class Fn, class... ArgTypes> struct is_invocable_r; template <class R, class Fn, class... ArgTypes> // (C++14) inline constexpr bool is_invocable_r_v = is_invocable_r<R, Fn, ArgTypes...>::value; // is_nothrow_invocable template <class Fn, class... ArgTypes> struct is_nothrow_invocable; template <class Fn, class... ArgTypes> // (C++14) inline constexpr bool is_nothrow_invocable_v = is_nothrow_invocable<Fn, ArgTypes...>::value; // is_nothrow_invocable_r template <class R, class Fn, class... ArgTypes> struct is_nothrow_invocable_r; template <class R, class Fn, class... ArgTypes> // (C++14) inline constexpr bool is_nothrow_invocable_r_v = is_nothrow_invocable_r<R, Fn, ArgTypes...>::value; } #define EGGS_INVOKE(f, ...) // (extension) #define EGGS_INVOKE_R(R, f, ...) // (extension)
Define INVOKE(f, t1, t2, ..., tN)
as follows:
(t1.*f)(t2, ..., tN)
when f
is a pointer to a member function of a
class T
and std::is_base_of_v<T, std::remove_reference_t<decltype(t1)>>
is true
;
(t1.get().*f)(t2, ..., tN)
when f
is a pointer to a member function of a
class T
and std::remove_cvref_t<decltype(t1)>
is a specialization of
std::reference_wrapper
;
((*t1).*f)(t2, ..., tN)
when f
is a pointer to a member function of a
class T
and t1
does not satisfy the previous two items;
t1.*f
when N == 1
and f
is a pointer to data member of a class T
and
std::is_base_of_v<T, std::remove_reference_t<decltype(t1)>>
is true
;
t1.get().*f
when N == 1
and f
is a pointer to data member of a class
T
and std::remove_cvref_t<decltype(t1)>
is a specialization of
std::reference_wrapper
;
(*t1).*f
when N == 1
and f
is a pointer to data member of a class T
and t1
does not satisfy the previous two items;
f(t1, t2, ..., tN)
in all other cases.
Define INVOKE<R>(f, t1, t2, ..., tN)
as static_cast<void>(INVOKE(f, t1, t2, ..., tN))
if R
is cv void
, otherwise INVOKE(f, t1, t2, ..., tN)
implicitly converted to R
.
invoke
template <class F, class... Args> constexpr invoke_result_t<F, Args...> invoke(F&& f, Args&&... args) noexcept(is_nothrow_invocable_v<F, Args...>);
Returns: INVOKE(std::forward<F>(f), std::forward<Args>(args)...)
.
Remarks: This function shall not participate in overload resolution unless
is_invocable_v<F, Args...>
is true
.
invoke_r
template <class R, class F, class... Args> // (extension) constexpr R INVOKE(F&& f, Args&&... args) noexcept(is_nothrow_invocable_r_v<R, F, Args...>);
Returns: INVOKE<R>(std::forward<F>(f), std::forward<Args>(args)...)
.
Remarks: This function shall not participate in overload resolution unless
is_invocable_r_v<R, F, Args...>
is true
.
invoke_result
template <class Fn, class... ArgTypes> struct invoke_result;
Comments: If the expression INVOKE(std::declval<Fn>(), std::declval<ArgTypes>()...)
is well-formed when treated as an unevaluated
operand, the member typedef type
names the type decltype(INVOKE(std::declval<Fn>(), std::declval<ArgTypes>()...))
; otherwise, there shall be no member type
.
Access checking is performed as if in a context unrelated to Fn
and
ArgTypes
. Only the validity of the immediate context of the expression is
considered.
Preconditions: Fn
and all types in the template parameter pack ArgTypes
are complete types, cv void
, or arrays of unknown bound.
template <class Fn, class... ArgTypes> using invoke_result_t = typename invoke_result<Fn, ArgTypes...>::type;
is_invocable
template <class Fn, class... ArgTypes> struct is_invocable;
Condition: The expression INVOKE(std::declval<Fn>(), std::declval<ArgTypes>()...)
is well-formed when treated as an unevaluated
operand.
Comments: Fn
and all types in the template parameter pack ArgTypes
shall be complete types, cv void
, or arrays of unknown bound.
template <class Fn, class... ArgTypes> // (C++14) inline constexpr bool is_invocable_v = is_invocable<Fn, ArgTypes...>::value;
is_invocable_r
// is_invocable_r template <class R, class Fn, class... ArgTypes> struct is_invocable_r;
Condition: The expression INVOKE<R>(std::declval<Fn>(), std::declval<ArgTypes>()...)
is well-formed when treated as an unevaluated
operand.
Comments: Fn
, R
, and all types in the template parameter pack
ArgTypes
shall be complete types, cv void
, or arrays of unknown bound.
template <class R, class Fn, class... ArgTypes> // (C++14) inline constexpr bool is_invocable_r_v = is_invocable_r<R, Fn, ArgTypes...>::value;
is_nothrow_invocable
// is_nothrow_invocable template <class Fn, class... ArgTypes> struct is_nothrow_invocable;
Condition: is_invocable_v<Fn, ArgTypes...>
is true
and the
expression INVOKE(std::declval<Fn>(), std::declval<ArgTypes>()...)
is
known not to throw any exceptions.
Comments: Fn
and all types in the template parameter pack ArgTypes
shall be complete types, cv void
, or arrays of unknown bound.
template <class Fn, class... ArgTypes> // (C++14) inline constexpr bool is_nothrow_invocable_v = is_nothrow_invocable<Fn, ArgTypes...>::value;
is_nothrow_invocable_r
// is_nothrow_invocable_r template <class R, class Fn, class... ArgTypes> struct is_nothrow_invocable_r;
Condition: is_invocable_r_v<R, Fn, ArgTypes...>
is true
and the
expression INVOKE<R>(std::declval<Fn>(), std::declval<ArgTypes>()...)
is
known not to throw any exceptions.
Comments: Fn
, R
, and all types in the template parameter pack
ArgTypes
shall be complete types, cv void
, or arrays of unknown bound.
template <class R, class Fn, class... ArgTypes> // (C++14) inline constexpr bool is_nothrow_invocable_r_v = is_nothrow_invocable_r<R, Fn, ArgTypes...>::value;
EGGS_INVOKE
#define EGGS_INVOKE(f, ...) // (extension)
INVOKE(f __VA_OPT__(,) __VA_ARGS__)
.EGGS_INVOKE_R
#define EGGS_INVOKE_R(R, f, ...) // (extension)
INVOKE<R>(f __VA_OPT__(,) __VA_ARGS__)
.Copyright Agustín Bergé, Fusion Fenix 2017-2020
Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)