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.
invoketemplate <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_rtemplate <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_resulttemplate <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_invocabletemplate <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)