From b4bf5ed575da01e0846bc1f465443b2335219b53 Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Wed, 10 May 2017 01:51:08 -0400 Subject: [PATCH] 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. --- include/pybind11/detail/common.h | 25 +++++++++++++++++++++++++ include/pybind11/numpy.h | 6 +++--- include/pybind11/pybind11.h | 11 +++-------- 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/include/pybind11/detail/common.h b/include/pybind11/detail/common.h index c7b69f58b..7397e2be9 100644 --- a/include/pybind11/detail/common.h +++ b/include/pybind11/detail/common.h @@ -689,6 +689,31 @@ template struct is_input_iterator()), decltype(++std::declval())>> : std::true_type {}; +template using is_function_pointer = bool_constant< + std::is_pointer::value && std::is_function::type>::value>; + +template struct strip_function_object { + using type = typename remove_class::type; +}; + +// Extracts the function signature from a function, function pointer or lambda. +template > +using function_signature_t = conditional_t< + std::is_function::value, + F, + typename conditional_t< + std::is_pointer::value || std::is_member_pointer::value, + std::remove_pointer, + strip_function_object + >::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 using is_lambda = satisfies_none_of, + 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 *) { } diff --git a/include/pybind11/numpy.h b/include/pybind11/numpy.h index 4ee256192..4bea46029 100644 --- a/include/pybind11/numpy.h +++ b/include/pybind11/numpy.h @@ -1571,10 +1571,10 @@ vectorize(Return (*f) (Args ...)) { } // lambda vectorizer: -template ::operator())>::type> +template ::value, int> = 0> auto vectorize(Func &&f) -> decltype( - detail::vectorize_extractor(std::forward(f), (FuncType *) nullptr)) { - return detail::vectorize_extractor(std::forward(f), (FuncType *) nullptr); + detail::vectorize_extractor(std::forward(f), (detail::function_signature_t *) nullptr)) { + return detail::vectorize_extractor(std::forward(f), (detail::function_signature_t *) nullptr); } // Vectorize a class method (non-const): diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 9bf39d145..bd0ee2733 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -58,16 +58,11 @@ public: } /// Construct a cpp_function from a lambda function (possibly with internal state) - template , - std::is_function, std::is_pointer, std::is_member_pointer - >::value> - > + template ::value>> cpp_function(Func &&f, const Extra&... extra) { - using FuncType = typename detail::remove_class::operator())>::type; initialize(std::forward(f), - (FuncType *) nullptr, extra...); + (detail::function_signature_t *) nullptr, extra...); } /// Construct a cpp_function from a class method (non-const)