Added metatypes for dealing with functions/lambdas

`function_signature_t` extracts the function type from a function,
function pointer, or lambda.

`is_lambda` (which is really
`is_not_a_function_or_pointer_or_member_pointer`, but that name is a
bit too long) checks whether the type is (in the approprate context) a
lambda.

`is_function_pointer` checks whether the type is a pointer to a
function.
This commit is contained in:
Jason Rhinelander 2017-05-10 01:51:08 -04:00
parent fd81a03ec9
commit b4bf5ed575
3 changed files with 31 additions and 11 deletions

View File

@ -689,6 +689,31 @@ template <typename T>
struct is_input_iterator<T, void_t<decltype(*std::declval<T &>()), decltype(++std::declval<T &>())>>
: std::true_type {};
template <typename T> using is_function_pointer = bool_constant<
std::is_pointer<T>::value && std::is_function<typename std::remove_pointer<T>::type>::value>;
template <typename F> struct strip_function_object {
using type = typename remove_class<decltype(&F::operator())>::type;
};
// Extracts the function signature from a function, function pointer or lambda.
template <typename Function, typename F = remove_reference_t<Function>>
using function_signature_t = conditional_t<
std::is_function<F>::value,
F,
typename conditional_t<
std::is_pointer<F>::value || std::is_member_pointer<F>::value,
std::remove_pointer<F>,
strip_function_object<F>
>::type
>;
/// Returns true if the type looks like a lambda: that is, isn't a function, pointer or member
/// pointer. Note that this can catch all sorts of other things, too; this is intended to be used
/// in a place where passing a lambda makes sense.
template <typename T> using is_lambda = satisfies_none_of<remove_reference_t<T>,
std::is_function, std::is_pointer, std::is_member_pointer>;
/// Ignore that a variable is unused in compiler warnings
inline void ignore_unused(const int *) { }

View File

@ -1571,10 +1571,10 @@ vectorize(Return (*f) (Args ...)) {
}
// lambda vectorizer:
template <typename Func, typename FuncType = typename detail::remove_class<decltype(&detail::remove_reference_t<Func>::operator())>::type>
template <typename Func, detail::enable_if_t<detail::is_lambda<Func>::value, int> = 0>
auto vectorize(Func &&f) -> decltype(
detail::vectorize_extractor(std::forward<Func>(f), (FuncType *) nullptr)) {
return detail::vectorize_extractor(std::forward<Func>(f), (FuncType *) nullptr);
detail::vectorize_extractor(std::forward<Func>(f), (detail::function_signature_t<Func> *) nullptr)) {
return detail::vectorize_extractor(std::forward<Func>(f), (detail::function_signature_t<Func> *) nullptr);
}
// Vectorize a class method (non-const):

View File

@ -58,16 +58,11 @@ public:
}
/// Construct a cpp_function from a lambda function (possibly with internal state)
template <typename Func, typename... Extra, typename = detail::enable_if_t<
detail::satisfies_none_of<
detail::remove_reference_t<Func>,
std::is_function, std::is_pointer, std::is_member_pointer
>::value>
>
template <typename Func, typename... Extra,
typename = detail::enable_if_t<detail::is_lambda<Func>::value>>
cpp_function(Func &&f, const Extra&... extra) {
using FuncType = typename detail::remove_class<decltype(&detail::remove_reference_t<Func>::operator())>::type;
initialize(std::forward<Func>(f),
(FuncType *) nullptr, extra...);
(detail::function_signature_t<Func> *) nullptr, extra...);
}
/// Construct a cpp_function from a class method (non-const)