Commit 1fbecf3f authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook GitHub Bot

A few tweaks to SFINAE in Function

Summary: [Folly] A few simplifying tweaks to SFINAE in `Function`.

Reviewed By: aary

Differential Revision: D23798698

fbshipit-source-id: e5a3ecfe755f6eb371c253cfb925a23d4f5d29e4
parent a34629de
...@@ -263,36 +263,22 @@ using IsSmall = Conjunction< ...@@ -263,36 +263,22 @@ using IsSmall = Conjunction<
using SmallTag = std::true_type; using SmallTag = std::true_type;
using HeapTag = std::false_type; using HeapTag = std::false_type;
template <typename T>
struct NotFunction : std::true_type {};
template <typename T>
struct NotFunction<Function<T>> : std::false_type {};
template <typename T>
using EnableIfNotFunction =
typename std::enable_if<NotFunction<T>::value>::type;
struct CoerceTag {}; struct CoerceTag {};
template <typename, typename T>
struct IsFunctionNullptrTestable : std::false_type {};
template <typename T> template <typename T>
struct IsFunctionNullptrTestable< using FunctionNullptrTest =
void_t<decltype( decltype(static_cast<bool>(static_cast<T const&>(T(nullptr)) == nullptr));
static_cast<bool>(static_cast<T const&>(T(nullptr)) == nullptr))>,
T> : std::true_type {};
template <typename T> template <
constexpr std::enable_if_t< // typename T,
!IsFunctionNullptrTestable<void, T>::value, std::enable_if_t<!is_detected_v<FunctionNullptrTest, T>, int> = 0>
std::false_type> constexpr bool isEmptyFunction(T const&) {
isEmptyFunction(T const&) { return false;
return {};
} }
template <typename T> template <
constexpr std::enable_if_t<IsFunctionNullptrTestable<void, T>::value, bool> typename T,
isEmptyFunction(T const& t) { std::enable_if_t<is_detected_v<FunctionNullptrTest, T>, int> = 0>
constexpr bool isEmptyFunction(T const& t) {
return static_cast<bool>(t == nullptr); return static_cast<bool>(t == nullptr);
} }
...@@ -739,7 +725,8 @@ class Function final : private detail::function::FunctionTraits<FunctionType> { ...@@ -739,7 +725,8 @@ class Function final : private detail::function::FunctionTraits<FunctionType> {
*/ */
template < template <
typename Fun, typename Fun,
typename = detail::function::EnableIfNotFunction<Fun>, typename =
std::enable_if_t<!detail::is_similar_instantiation_v<Function, Fun>>,
typename = typename Traits::template ResultOf<Fun>> typename = typename Traits::template ResultOf<Fun>>
/* implicit */ Function(Fun fun) noexcept( /* implicit */ Function(Fun fun) noexcept(
IsSmall<Fun>::value&& noexcept(Fun(std::declval<Fun>()))) IsSmall<Fun>::value&& noexcept(Fun(std::declval<Fun>())))
......
...@@ -67,6 +67,15 @@ FOLLY_INLINE_VARIABLE constexpr bool is_instantiation_of_v<C, C<T...>> = true; ...@@ -67,6 +67,15 @@ FOLLY_INLINE_VARIABLE constexpr bool is_instantiation_of_v<C, C<T...>> = true;
template <template <typename...> class C, typename... T> template <template <typename...> class C, typename... T>
struct is_instantiation_of : bool_constant<is_instantiation_of_v<C, T...>> {}; struct is_instantiation_of : bool_constant<is_instantiation_of_v<C, T...>> {};
template <typename, typename>
FOLLY_INLINE_VARIABLE constexpr bool is_similar_instantiation_v = false;
template <template <typename...> class C, typename... A, typename... B>
FOLLY_INLINE_VARIABLE constexpr bool
is_similar_instantiation_v<C<A...>, C<B...>> = true;
template <typename A, typename B>
struct is_similar_instantiation
: bool_constant<is_similar_instantiation_v<A, B>> {};
} // namespace detail } // namespace detail
namespace detail { namespace detail {
......
...@@ -425,6 +425,20 @@ TEST(Traits, is_instantiation_of) { ...@@ -425,6 +425,20 @@ TEST(Traits, is_instantiation_of) {
EXPECT_FALSE((detail::is_instantiation_of<A, B>::value)); EXPECT_FALSE((detail::is_instantiation_of<A, B>::value));
} }
TEST(Traits, is_similar_instantiation_v) {
EXPECT_TRUE((detail::is_similar_instantiation_v<A<int>, A<long>>));
EXPECT_FALSE((detail::is_similar_instantiation_v<A<int>, tag_t<int>>));
EXPECT_FALSE((detail::is_similar_instantiation_v<A<int>, B>));
EXPECT_FALSE((detail::is_similar_instantiation_v<B, B>));
}
TEST(Traits, is_similar_instantiation) {
EXPECT_TRUE((detail::is_similar_instantiation<A<int>, A<long>>::value));
EXPECT_FALSE((detail::is_similar_instantiation<A<int>, tag_t<int>>::value));
EXPECT_FALSE((detail::is_similar_instantiation<A<int>, B>::value));
EXPECT_FALSE((detail::is_similar_instantiation<B, B>::value));
}
TEST(Traits, is_constexpr_default_constructible) { TEST(Traits, is_constexpr_default_constructible) {
EXPECT_TRUE(is_constexpr_default_constructible_v<int>); EXPECT_TRUE(is_constexpr_default_constructible_v<int>);
EXPECT_TRUE(is_constexpr_default_constructible<int>{}); EXPECT_TRUE(is_constexpr_default_constructible<int>{});
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment