Skip to content

Commit

Permalink
constructor deduction guides for folly::Function
Browse files Browse the repository at this point in the history
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
  • Loading branch information
yfeldblum authored and facebook-github-bot committed Dec 18, 2023
1 parent 13435f2 commit a1ff042
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 0 deletions.
30 changes: 30 additions & 0 deletions folly/Function.h
Original file line number Diff line number Diff line change
Expand Up @@ -1017,6 +1017,36 @@ Function<ReturnType(Args...) const noexcept> constCastFunction(
}
#endif

namespace detail {

template <typename Void, typename>
struct function_ctor_deduce_;

template <typename P>
struct function_ctor_deduce_<
std::enable_if_t<std::is_function<std::remove_pointer_t<P>>::value>,
P> {
using type = std::remove_pointer_t<P>;
};

template <typename F>
struct function_ctor_deduce_<void_t<decltype(&F::operator())>, F> {
using type =
typename member_pointer_traits<decltype(&F::operator())>::member_type;
};

template <typename F>
using function_ctor_deduce_t = typename function_ctor_deduce_<void, F>::type;

} // namespace detail

#if FOLLY_HAS_DEDUCTION_GUIDES

template <typename F>
Function(F) -> Function<detail::function_ctor_deduce_t<F>>;

#endif

/**
* @class folly::FunctionRef
*
Expand Down
57 changes: 57 additions & 0 deletions folly/test/FunctionTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,63 @@ static_assert( //

static_assert(std::is_nothrow_destructible<Function<int(int)>>::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<void()>,
decltype(Function{ctor_guide::fn})>);
static_assert( //
std::is_same_v< //
Function<void()>,
decltype(Function{&ctor_guide::fn})>);
static_assert( //
std::is_same_v< //
Function<void()>,
decltype(Function{ctor_guide::call{}})>);
static_assert( //
std::is_same_v< //
Function<void() const>,
decltype(Function{ctor_guide::call_c{}})>);
#if FOLLY_HAVE_NOEXCEPT_FUNCTION_TYPE
static_assert( //
std::is_same_v< //
Function<void() noexcept>,
decltype(Function{ctor_guide::fn_nx})>);
static_assert( //
std::is_same_v< //
Function<void() noexcept>,
decltype(Function{&ctor_guide::fn_nx})>);
static_assert( //
std::is_same_v< //
Function<void() noexcept>,
decltype(Function{ctor_guide::call_nx{}})>);
static_assert( //
std::is_same_v< //
Function<void() const noexcept>,
decltype(Function{ctor_guide::call_c_nx{}})>);
#endif

#endif

struct RecStd {
using type = std::function<RecStd()>;
/* implicit */ RecStd(type f) : func(f) {}
Expand Down

0 comments on commit a1ff042

Please sign in to comment.