mirror of
https://github.com/Naios/continuable.git
synced 2025-12-06 16:56:44 +08:00
Move is_invokeable to traits and rename it to is_invokeable_from_tuple
This commit is contained in:
parent
eafbe4b37d
commit
d1e0c1d606
@ -31,8 +31,6 @@
|
|||||||
#ifndef CONTINUABLE_DETAIL_CONTAINER_CATEGORY_HPP_INCLUDED
|
#ifndef CONTINUABLE_DETAIL_CONTAINER_CATEGORY_HPP_INCLUDED
|
||||||
#define CONTINUABLE_DETAIL_CONTAINER_CATEGORY_HPP_INCLUDED
|
#define CONTINUABLE_DETAIL_CONTAINER_CATEGORY_HPP_INCLUDED
|
||||||
|
|
||||||
#include <continuable/continuable-api.hpp>
|
|
||||||
|
|
||||||
namespace cti {
|
namespace cti {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
namespace traversal {
|
namespace traversal {
|
||||||
|
|||||||
@ -408,6 +408,35 @@ constexpr auto merge(identity<LeftArgs...> /*left*/,
|
|||||||
std::forward<Rest>(rest)...);
|
std::forward<Rest>(rest)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
template <typename T, typename Args, typename = traits::void_t<>>
|
||||||
|
struct is_invokable_impl : std::common_type<std::false_type> {};
|
||||||
|
|
||||||
|
template <typename T, typename... Args>
|
||||||
|
struct is_invokable_impl<
|
||||||
|
T, std::tuple<Args...>,
|
||||||
|
void_t<decltype(std::declval<T>()(std::declval<Args>()...))>>
|
||||||
|
: std::common_type<std::true_type> {};
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
/// Deduces to a std::true_type if the given type is callable with the arguments
|
||||||
|
/// inside the given tuple.
|
||||||
|
/// The main reason for implementing it with the detection idiom instead of
|
||||||
|
/// hana like detection is that MSVC has issues with capturing raw template
|
||||||
|
/// arguments inside lambda closures.
|
||||||
|
///
|
||||||
|
/// ```cpp
|
||||||
|
/// traits::is_invokable<object, std::tuple<Args...>>
|
||||||
|
/// ```
|
||||||
|
template <typename T, typename Args>
|
||||||
|
using is_invokable_from_tuple =
|
||||||
|
typename detail::is_invokable_impl<T, Args>::type;
|
||||||
|
|
||||||
|
// Checks whether the given callable object is invocable with the given
|
||||||
|
// arguments. This doesn't take member functions into account!
|
||||||
|
template <typename T, typename... Args>
|
||||||
|
using is_invocable = is_invokable_from_tuple<T, std::tuple<Args...>>;
|
||||||
|
|
||||||
/// Deduces to a std::false_type
|
/// Deduces to a std::false_type
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using fail = std::integral_constant<bool, !std::is_same<T, T>::value>;
|
using fail = std::integral_constant<bool, !std::is_same<T, T>::value>;
|
||||||
@ -415,6 +444,7 @@ using fail = std::integral_constant<bool, !std::is_same<T, T>::value>;
|
|||||||
#ifdef CONTINUABLE_HAS_CXX17_DISJUNCTION
|
#ifdef CONTINUABLE_HAS_CXX17_DISJUNCTION
|
||||||
using std::disjunction;
|
using std::disjunction;
|
||||||
#else
|
#else
|
||||||
|
namespace detail {
|
||||||
/// Declares a C++14 polyfill for C++17 std::disjunction.
|
/// Declares a C++14 polyfill for C++17 std::disjunction.
|
||||||
template <typename Args, typename = void_t<>>
|
template <typename Args, typename = void_t<>>
|
||||||
struct disjunction_impl : std::common_type<std::false_type> {};
|
struct disjunction_impl : std::common_type<std::false_type> {};
|
||||||
@ -422,8 +452,10 @@ template <typename... Args>
|
|||||||
struct disjunction_impl<identity<Args...>,
|
struct disjunction_impl<identity<Args...>,
|
||||||
void_t<std::enable_if_t<bool(Args::value)>...>>
|
void_t<std::enable_if_t<bool(Args::value)>...>>
|
||||||
: std::common_type<std::true_type> {};
|
: std::common_type<std::true_type> {};
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
using disjunction = disjunction_impl<identity<Args...>>;
|
using disjunction = typename detail::disjunction_impl<identity<Args...>>::type;
|
||||||
#endif // CONTINUABLE_HAS_CXX17_DISJUNCTION
|
#endif // CONTINUABLE_HAS_CXX17_DISJUNCTION
|
||||||
|
|
||||||
} // namespace traits
|
} // namespace traits
|
||||||
|
|||||||
@ -304,7 +304,8 @@ template <typename T, typename E, typename = void>
|
|||||||
struct has_push_back : std::false_type {};
|
struct has_push_back : std::false_type {};
|
||||||
template <typename T, typename E>
|
template <typename T, typename E>
|
||||||
struct has_push_back<
|
struct has_push_back<
|
||||||
T, E, std::void_t<decltype(std::declval<T>().push_back(std::declval<E>()))>>
|
T, E,
|
||||||
|
traits::void_t<decltype(std::declval<T>().push_back(std::declval<E>()))>>
|
||||||
: std::true_type {};
|
: std::true_type {};
|
||||||
|
|
||||||
/// Specialization for a container with a single type T
|
/// Specialization for a container with a single type T
|
||||||
@ -554,7 +555,7 @@ struct tuple_like_remapper<strategy_traverse_tag, M, Base<OldArgs...>,
|
|||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
auto operator()(Args&&... args)
|
auto operator()(Args&&... args)
|
||||||
-> std::void_t<typename invoke_result<M, OldArgs>::type...> {
|
-> traits::void_t<typename invoke_result<M, OldArgs>::type...> {
|
||||||
int dummy[] = {0, ((void)mapper_(std::forward<Args>(args)), 0)...};
|
int dummy[] = {0, ((void)mapper_(std::forward<Args>(args)), 0)...};
|
||||||
(void)dummy;
|
(void)dummy;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,29 +48,6 @@ template <typename... T>
|
|||||||
void unused(T&&...) {
|
void unused(T&&...) {
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
template <typename T, typename Args, typename = traits::void_t<>>
|
|
||||||
struct is_invokable_impl : std::common_type<std::false_type> {};
|
|
||||||
|
|
||||||
template <typename T, typename... Args>
|
|
||||||
struct is_invokable_impl<
|
|
||||||
T, std::tuple<Args...>,
|
|
||||||
traits::void_t<decltype(std::declval<T>()(std::declval<Args>()...))>>
|
|
||||||
: std::common_type<std::true_type> {};
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
/// Deduces to a std::true_type if the given type is callable with the arguments
|
|
||||||
/// inside the given tuple.
|
|
||||||
/// The main reason for implementing it with the detection idiom instead of
|
|
||||||
/// hana like detection is that MSVC has issues with capturing raw template
|
|
||||||
/// arguments inside lambda closures.
|
|
||||||
///
|
|
||||||
/// ```cpp
|
|
||||||
/// traits::is_invokable<object, std::tuple<Args...>>
|
|
||||||
/// ```
|
|
||||||
template <typename T, typename Args>
|
|
||||||
using is_invokable = typename detail::is_invokable_impl<T, Args>::type;
|
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
/// Forwards every element in the tuple except the last one
|
/// Forwards every element in the tuple except the last one
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -117,7 +94,8 @@ auto partial_invoke_impl(std::false_type, T&& callable,
|
|||||||
auto next = forward_except_last(std::move(args));
|
auto next = forward_except_last(std::move(args));
|
||||||
|
|
||||||
// Test whether we are able to call the function with the given tuple
|
// Test whether we are able to call the function with the given tuple
|
||||||
is_invokable<decltype(callable), decltype(next)> is_invokable;
|
traits::is_invokable_from_tuple<decltype(callable), decltype(next)>
|
||||||
|
is_invokable;
|
||||||
|
|
||||||
return partial_invoke_impl(is_invokable, std::forward<T>(callable),
|
return partial_invoke_impl(is_invokable, std::forward<T>(callable),
|
||||||
std::move(next));
|
std::move(next));
|
||||||
@ -150,7 +128,8 @@ auto partial_invoke_impl_shortcut(std::false_type failed, T&& callable,
|
|||||||
template <typename T, typename... Args>
|
template <typename T, typename... Args>
|
||||||
/*keep this inline*/ inline auto partial_invoke(T&& callable, Args&&... args) {
|
/*keep this inline*/ inline auto partial_invoke(T&& callable, Args&&... args) {
|
||||||
// Test whether we are able to call the function with the given arguments.
|
// Test whether we are able to call the function with the given arguments.
|
||||||
is_invokable<decltype(callable), std::tuple<Args...>> is_invokable;
|
traits::is_invokable_from_tuple<decltype(callable), std::tuple<Args...>>
|
||||||
|
is_invokable;
|
||||||
|
|
||||||
// The implementation is done in a shortcut way so there are less
|
// The implementation is done in a shortcut way so there are less
|
||||||
// type instantiations needed to call the callable with its full signature.
|
// type instantiations needed to call the callable with its full signature.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user