From a1ff042d51c73341bc6326b86a0d4fe6381846ae Mon Sep 17 00:00:00 2001 From: Yedidya Feldblum Date: Sun, 17 Dec 2023 16:21:03 -0800 Subject: [PATCH] constructor deduction guides for folly::Function Summary: Add constructor deduction guides for `folly::Function`, parallel to the constructor deduction guides for `std::function`. https://en.cppreference.com/w/cpp/utility/functional/function/deduction_guides Supports `const`- and `noexcept`-qualified function-pointers and unambiguously-invocable objects and lifts them into the deduced signature parameterizing `folly::Function`, which is not supported for `std::function`. Note: Curiously, `std::move_only_function` has no constructor deduction guides. Reviewed By: luciang Differential Revision: D52212897 fbshipit-source-id: 1763693159f64933d0e25044bd988ab2fb2e3ef2 --- folly/Function.h | 30 +++++++++++++++++++ folly/test/FunctionTest.cpp | 57 +++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) diff --git a/folly/Function.h b/folly/Function.h index ba1eff22cba..9986405767d 100644 --- a/folly/Function.h +++ b/folly/Function.h @@ -1017,6 +1017,36 @@ Function constCastFunction( } #endif +namespace detail { + +template +struct function_ctor_deduce_; + +template +struct function_ctor_deduce_< + std::enable_if_t>::value>, + P> { + using type = std::remove_pointer_t

; +}; + +template +struct function_ctor_deduce_, F> { + using type = + typename member_pointer_traits::member_type; +}; + +template +using function_ctor_deduce_t = typename function_ctor_deduce_::type; + +} // namespace detail + +#if FOLLY_HAS_DEDUCTION_GUIDES + +template +Function(F) -> Function>; + +#endif + /** * @class folly::FunctionRef * diff --git a/folly/test/FunctionTest.cpp b/folly/test/FunctionTest.cpp index 371a8b8414d..a80b9769a13 100644 --- a/folly/test/FunctionTest.cpp +++ b/folly/test/FunctionTest.cpp @@ -304,6 +304,63 @@ static_assert( // static_assert(std::is_nothrow_destructible>::value, ""); +#if FOLLY_HAS_DEDUCTION_GUIDES + +struct ctor_guide { + static void fn(); + static void fn_nx() noexcept; + + struct call { + void operator()(); + }; + struct call_c { + void operator()() const; + }; + struct call_nx { + void operator()() noexcept; + }; + struct call_c_nx { + void operator()() const noexcept; + }; +}; + +static_assert( // + std::is_same_v< // + Function, + decltype(Function{ctor_guide::fn})>); +static_assert( // + std::is_same_v< // + Function, + decltype(Function{&ctor_guide::fn})>); +static_assert( // + std::is_same_v< // + Function, + decltype(Function{ctor_guide::call{}})>); +static_assert( // + std::is_same_v< // + Function, + decltype(Function{ctor_guide::call_c{}})>); +#if FOLLY_HAVE_NOEXCEPT_FUNCTION_TYPE +static_assert( // + std::is_same_v< // + Function, + decltype(Function{ctor_guide::fn_nx})>); +static_assert( // + std::is_same_v< // + Function, + decltype(Function{&ctor_guide::fn_nx})>); +static_assert( // + std::is_same_v< // + Function, + decltype(Function{ctor_guide::call_nx{}})>); +static_assert( // + std::is_same_v< // + Function, + decltype(Function{ctor_guide::call_c_nx{}})>); +#endif + +#endif + struct RecStd { using type = std::function; /* implicit */ RecStd(type f) : func(f) {}