kfr

Fast, modern C++ DSP framework, FFT, Sample Rate Conversion, FIR/IIR/Biquad Filters (SSE, AVX, AVX-512, ARM NEON)
Log | Files | Refs | README

commit 23281a48b3ddbf2f6971d0c1830375dea15e733e
parent 08e58cf4ec791a7f2f6423a7cadfacafd9529348
Author: d.levin256@gmail.com <d.levin256@gmail.com>
Date:   Mon,  2 Dec 2019 19:20:08 +0000

is_invocable_r

Diffstat:
Minclude/kfr/cometa.hpp | 28+++++++++++++++++++++++-----
Minclude/kfr/cometa/function.hpp | 5++++-
Mtests/generate_data.cpp | 1+
3 files changed, 28 insertions(+), 6 deletions(-)

diff --git a/include/kfr/cometa.hpp b/include/kfr/cometa.hpp @@ -573,7 +573,7 @@ struct concat_impl<T1, T2, T3, Ts...> using type = typename concat_impl<typename concat_impl<T1, T2>::type, T3, Ts...>::type; }; -template <typename Fn, typename Args, typename enable=void> +template <typename Fn, typename Args, typename enable = void> struct is_invocable_impl : std::false_type { }; @@ -584,6 +584,18 @@ struct is_invocable_impl<Fn, ctypes_t<Args...>, void_t<decltype(std::declval<Fn> { }; +template <typename Fn, typename Ret, typename Args, typename enable = void> +struct is_invocable_r_impl : std::false_type +{ +}; + +template <typename Fn, typename Ret, typename... Args> +struct is_invocable_r_impl<Fn, Ret, ctypes_t<Args...>, + void_t<decltype(std::declval<Fn>()(std::declval<Args>()...))>> +{ + static constexpr bool value = is_convertible<decltype(std::declval<Fn>()(std::declval<Args>()...)), Ret>; +}; + } // namespace details template <typename T1, typename... Ts> using concat_lists = typename details::concat_impl<decay<T1>, decay<Ts>...>::type; @@ -595,11 +607,17 @@ constexpr inline concat_lists<T1, Ts...> cconcat(T1, Ts...) } #ifdef __cpp_lib_is_invocable -template <typename T, typename... Args> -constexpr inline bool is_invocable = std::is_invocable<T, Args...>::value; +template <typename Fn, typename... Args> +constexpr inline bool is_invocable = std::is_invocable<Fn, Args...>::value; + +template <typename Ret, typename Fn, typename... Args> +constexpr inline bool is_invocable_r = std::is_invocable_r<Ret, Fn, Args...>::value; #else -template <typename T, typename... Args> -constexpr inline bool is_invocable = details::is_invocable_impl<T, ctypes_t<Args...>>::value; +template <typename Fn, typename... Args> +constexpr inline bool is_invocable = details::is_invocable_impl<Fn, ctypes_t<Args...>>::value; + +template <typename Ret, typename Fn, typename... Args> +constexpr inline bool is_invocable_r = details::is_invocable_r_impl<Ret, Fn, ctypes_t<Args...>>::value; #endif namespace details diff --git a/include/kfr/cometa/function.hpp b/include/kfr/cometa/function.hpp @@ -65,6 +65,8 @@ struct function_impl : public function_abstract<R, Args...> { inline static void* operator new(size_t size) noexcept { return aligned_allocate(size, alignof(Fn)); } inline static void operator delete(void* ptr) noexcept { return aligned_deallocate(ptr); } + +#ifdef __cpp_aligned_new inline static void* operator new(size_t size, std::align_val_t al) noexcept { return aligned_allocate(size, static_cast<size_t>(al)); @@ -73,6 +75,7 @@ struct function_impl : public function_abstract<R, Args...> { return aligned_deallocate(ptr); } +#endif template <typename Fn_> function_impl(Fn_ fn) : fn(std::forward<Fn_>(fn)) @@ -92,7 +95,7 @@ struct function<R(Args...)> function(nullptr_t) noexcept {} template <typename Fn, - typename = enable_if<is_invocable<R, Fn, Args...> && !is_same<decay<Fn>, function>>> + typename = enable_if<is_invocable_r<R, Fn, Args...> && !is_same<decay<Fn>, function>>> function(Fn fn) : impl(new details::function_impl<decay<Fn>, R, Args...>(std::move(fn))) { } diff --git a/tests/generate_data.cpp b/tests/generate_data.cpp @@ -86,6 +86,7 @@ int main() { using num = mpfr::number; mpfr::scoped_precision prec(512); + generate_test( cint<1>, "sin", [](const num& x) { return mpfr::sin(x); }, 0, M_PI * 2); generate_test(