invoke.h
Go to the documentation of this file.
#ifndef __utl_utility_invoke_h__
#define __utl_utility_invoke_h__
#include <utl/core/impl.h>
#include <utl/meta/meta.h>
#include <type_traits>
#include <functional>
#include <utility>
namespace utl {
namespace detail {
template <class T>
struct is_ref_wrapper : meta::false_ {};
template <class U>
struct is_ref_wrapper<std::reference_wrapper<U>> : meta::true_ {};
// 1
template <class T, class Type, class T1, class... Args,
meta::enable_if_t<
std::is_member_function_pointer<std::decay_t<Type T::*>>::value &&
std::is_base_of<T, std::decay_t<T1>>::value,
int> =0
>
decltype(auto) invoke_impl_(Type T::* f, T1&& t1, Args&&... args) {
return (std::forward<T1>(t1).*f)(std::forward<Args>(args)...);
}
// 2
template <class T, class Type, class T1, class... Args,
meta::enable_if_t<
std::is_member_function_pointer<std::decay_t<Type T::*>>::value &&
is_ref_wrapper<std::decay_t<T1>>::value,
int> =0
>
decltype(auto) invoke_impl_(Type T::* f, T1&& t1, Args&&... args) {
return (t1.get().*f)(std::forward<Args>(args)...);
}
// 3
template <class T, class Type, class T1, class... Args,
meta::enable_if_t<
std::is_member_function_pointer<std::decay_t<Type T::*>>::value &&
!std::is_base_of<T, std::decay_t<T1>>::value &&
!is_ref_wrapper<std::decay_t<T1>>::value,
int> =0
>
decltype(auto) invoke_impl_(Type T::* f, T1&& t1, Args&&... args) {
return ((*std::forward<T1>(t1)).*f)(std::forward<Args>(args)...);
}
// 4
template <class T, class Type, class T1, class... Args,
meta::enable_if_t<
std::is_member_object_pointer<std::decay_t<Type T::*>>::value &&
std::is_base_of<T, std::decay_t<T1>>::value,
int> =0
>
decltype(auto) invoke_impl_(Type T::* f, T1&& t1, Args&&... args) {
return std::forward<T1>(t1).*f;
}
// 5
template <class T, class Type, class T1, class... Args,
meta::enable_if_t<
std::is_member_object_pointer<std::decay_t<Type T::*>>::value &&
is_ref_wrapper<std::decay_t<T1>>::value,
int> =0
>
decltype(auto) invoke_impl_(Type T::* f, T1&& t1, Args&&... args) {
return t1.get().*f;
}
// 6
template <class T, class Type, class T1, class... Args,
meta::enable_if_t<
std::is_member_object_pointer<std::decay_t<Type T::*>>::value &&
!std::is_base_of<T, std::decay_t<T1>>::value &&
!is_ref_wrapper<std::decay_t<T1>>::value,
int> =0
>
decltype(auto) invoke_impl_(Type T::* f, T1&& t1, Args&&... args) {
return (*std::forward<T1>(t1)).*f;
}
template <class F, class... Args>
decltype(auto) invoke_impl_(F&& f, Args&&... args) {
return std::forward<F>(f)(std::forward<Args>(args)...);
}
} // namespace detail
template<typename _Callable, typename... _Args>
inline decltype(auto) invoke(_Callable&& fn, _Args&&... args) {
return detail::invoke_impl_(
std::forward<_Callable>(fn), std::forward<_Args>(args)...
);
}
template <typename F, typename... Args>
struct is_invocable :
std::is_constructible<
std::function<void(Args ...)>,
std::reference_wrapper<typename std::remove_reference<F>::type>
> { };
template <typename R, typename F, typename... Args>
struct is_invocable_r :
std::is_constructible<
std::function<R(Args ...)>,
std::reference_wrapper<typename std::remove_reference<F>::type>
> { };
namespace detail {
template<typename _Callable, typename... _Args>
struct try_invoke {
using type = decltype (
detail::invoke_impl_(std::declval<_Callable&&>(), std::declval<_Args&&>()...)
);
};
template<bool B, typename _Callable, typename... _Args>
struct invoke_result_ {
using type = meta::nil_;
};
template <typename _Callable, typename... _Args>
struct invoke_result_ <true, _Callable, _Args...> {
using type = meta::invoke_t<
meta::quote<try_invoke>, _Callable, _Args...
>;
};
}
template <typename _Callable, typename... _Args>
using invoke_result = detail::invoke_result_<
is_invocable<_Callable, _Args...>::value,
_Callable,
_Args...
>;
template<typename _Callable, typename... _Args>
using invoke_result_t = meta::eval <
invoke_result<_Callable, _Args...>
>;
}
#endif /* __utl_utility_invoke_h__ */
utl::detail::invoke_impl_
decltype(auto) invoke_impl_(Type T::*f, T1 &&t1, Args &&... args)
Definition: invoke.h:51
utl::detail::invoke_result_
Definition: invoke.h:157
meta.h
Include all meta library.
utl::invoke
decltype(auto) invoke(_Callable &&fn, _Args &&... args)
Invoke a callable object (for C++14)
Definition: invoke.h:121
utl::meta::quote
Definition: invoke.h:234
utl::meta::true_
bool_< true > true_
The type used as a compile-time boolean with true value.
Definition: integral.h:68
std
STL namespace.
utl::detail::invoke_result_< true, _Callable, _Args... >::type
meta::invoke_t< meta::quote< try_invoke >, _Callable, _Args... > type
Definition: invoke.h:165
utl::meta::nil_
Definition: integral.h:43
utl::detail::is_ref_wrapper
Definition: invoke.h:40
utl::meta::false_
bool_< false > false_
The type used as a compile-time boolean with false value.
Definition: integral.h:69
utl::detail::try_invoke
Definition: invoke.h:150
utl::meta::eval
typename Tp::type eval
Type alias for Tp::type. Used to evaluate/extract return type of metafunctions.
Definition: integral.h:49
utl
STL&#39;s core language concepts.
Definition: _1wire.h:30
utl::meta::enable_if_t
eval< enable_if< If, _Tp > > enable_if_t
alias template for enable_if
Definition: sfinae.h:63
utl::invoke_result_t
meta::eval< invoke_result< _Callable, _Args... > > invoke_result_t
invoke_result_t (for C++14)
Definition: invoke.h:180
utl::is_invocable_r
std::is_invocable_r trait for C++11
Definition: invoke.h:138
utl::detail::try_invoke::type
decltype(detail::invoke_impl_(std::declval< _Callable && >(), std::declval< _Args && >()...)) type
Definition: invoke.h:153
utl::meta::invoke_t
eval< invoke< Fn, Args... > > invoke_t
Definition: invoke.h:88
impl.h
Implementation detail main forward header.
utl::is_invocable
std::is_invocable trait for C++11
Definition: invoke.h:130