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<
using SmallTag = std::true_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 {};
template <typename, typename T>
struct IsFunctionNullptrTestable : std::false_type {};
template <typename T>
struct IsFunctionNullptrTestable<
void_t<decltype(
static_cast<bool>(static_cast<T const&>(T(nullptr)) == nullptr))>,
T> : std::true_type {};
using FunctionNullptrTest =
decltype(static_cast<bool>(static_cast<T const&>(T(nullptr)) == nullptr));
template <typename T>
constexpr std::enable_if_t< //
!IsFunctionNullptrTestable<void, T>::value,
std::false_type>
isEmptyFunction(T const&) {
return {};
template <
typename T,
std::enable_if_t<!is_detected_v<FunctionNullptrTest, T>, int> = 0>
constexpr bool isEmptyFunction(T const&) {
return false;
}
template <typename T>
constexpr std::enable_if_t<IsFunctionNullptrTestable<void, T>::value, bool>
isEmptyFunction(T const& t) {
template <
typename T,
std::enable_if_t<is_detected_v<FunctionNullptrTest, T>, int> = 0>
constexpr bool isEmptyFunction(T const& t) {
return static_cast<bool>(t == nullptr);
}
......@@ -739,7 +725,8 @@ class Function final : private detail::function::FunctionTraits<FunctionType> {
*/
template <
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>>
/* implicit */ Function(Fun fun) noexcept(
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;
template <template <typename...> class C, typename... 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 {
......
......@@ -425,6 +425,20 @@ TEST(Traits, is_instantiation_of) {
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) {
EXPECT_TRUE(is_constexpr_default_constructible_v<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