Eggs.Invoke is a C++11/14/17/20 single-header implementation of
INVOKE and its related facilities. See the documentation at
http://eggs-cpp.github.io/invoke/.
Define INVOKE(f, t1, t2, ..., tN) as follows:
- 
(t1.*f)(t2, ..., tN)whenfis a pointer to a member function of a classTandstd::is_base_of_v<T, std::remove_reference_t<decltype(t1)>>istrue; - 
(t1.get().*f)(t2, ..., tN)whenfis a pointer to a member function of a classTandstd::remove_cvref_t<decltype(t1)>is a specialization ofstd::reference_wrapper; - 
((*t1).*f)(t2, ..., tN)whenfis a pointer to a member function of a classTandt1does not satisfy the previous two items; - 
t1.*fwhenN == 1andfis a pointer to data member of a classTandstd::is_base_of_v<T, std::remove_reference_t<decltype(t1)>>istrue; - 
t1.get().*fwhenN == 1andfis a pointer to data member of a classTandstd::remove_cvref_t<decltype(t1)>is a specialization ofstd::reference_wrapper; - 
(*t1).*fwhenN == 1andfis a pointer to data member of a classTandt1does 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.
template <class F, class... Args>
constexpr eggs::invoke_result_t<F, Args...> invoke(F&& f, Args&&... args)
    noexcept(eggs::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
eggs::is_invocable_v<F, Args...>istrue. 
template <class R, class F, class... Args> // (extension)
constexpr R eggs::invoke_r(F&& f, Args&&... args)
    noexcept(eggs::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
eggs::is_invocable_r_v<R, F, Args...>istrue. 
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 typedeftypenames the typedecltype(INVOKE(std::declval<Fn>(), std::declval<ArgTypes>()...)); otherwise, there shall be no membertype. Access checking is performed as if in a context unrelated toFnandArgTypes. Only the validity of the immediate context of the expression is considered. - 
Preconditions:
Fnand all types in the template parameter packArgTypesare complete types, cvvoid, or arrays of unknown bound. 
template <class Fn, class... ArgTypes>
using invoke_result_t = typename invoke_result<Fn, ArgTypes...>::type;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:
Fnand all types in the template parameter packArgTypesshall be complete types, cvvoid, or arrays of unknown bound. 
template <class Fn, class... ArgTypes> // (C++14)
inline constexpr bool is_invocable_v =
    eggs::is_invocable<Fn, ArgTypes...>::value;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 packArgTypesshall be complete types, cvvoid, or arrays of unknown bound. 
template <class R, class Fn, class... ArgTypes> // (C++14)
inline constexpr bool is_invocable_r_v =
    eggs::is_invocable_r<R, Fn, ArgTypes...>::value;template <class Fn, class... ArgTypes> struct is_nothrow_invocable;- 
Condition:
eggs::is_invocable_v<Fn, ArgTypes...>istrueand the expressionINVOKE(std::declval<Fn>(), std::declval<ArgTypes>()...)is known not to throw any exceptions. - 
Comments:
Fnand all types in the template parameter packArgTypesshall be complete types, cvvoid, or arrays of unknown bound. 
template <class Fn, class... ArgTypes> // (C++14)
inline constexpr bool is_nothrow_invocable_v =
    eggs::is_nothrow_invocable<Fn, ArgTypes...>::value;template <class R, class Fn, class... ArgTypes> struct is_nothrow_invocable_r;- 
Condition:
eggs::is_invocable_r_v<R, Fn, ArgTypes...>istrueand the expressionINVOKE<R>(std::declval<Fn>(), std::declval<ArgTypes>()...)is known not to throw any exceptions. - 
Comments:
Fn,R, and all types in the template parameter packArgTypesshall be complete types, cvvoid, or arrays of unknown bound. 
template <class R, class Fn, class... ArgTypes> // (C++14)
inline constexpr bool is_nothrow_invocable_r_v =
    eggs::is_nothrow_invocable_r<R, Fn, ArgTypes...>::value;#define EGGS_INVOKE(F, ...) // (extension)- Returns: 
INVOKE(F __VA_OPT__(,) __VA_ARGS__). 
#define EGGS_INVOKE_R(R, F, ...) // (extension)- Returns: 
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)