Skip to content

Commit

Permalink
folly concepts facebook#1 (facebook#2249)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: facebook#2249

We have a need for some common concepts that are used in many places.

This is a proposal, please let me know what you think.

Differential Revision: D59396081
  • Loading branch information
DenisYaroshevskiy authored and facebook-github-bot committed Aug 1, 2024
1 parent 6b0454f commit e689e2e
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 4 deletions.
30 changes: 30 additions & 0 deletions folly/Traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@ struct is_bounded_array : std::bool_constant<is_bounded_array_v<T>> {};
/// Note that this only works with type template parameters. It does not work
/// with non-type template parameters, template template parameters, or alias
/// templates.
///
/// NOTE: there is also `instantiation_of` concept
template <template <typename...> class, typename>
inline constexpr bool is_instantiation_of_v = false;
template <template <typename...> class C, typename... T>
Expand All @@ -174,6 +176,17 @@ template <template <typename...> class C, typename... T>
struct is_instantiation_of
: std::bool_constant<is_instantiation_of_v<C, T...>> {};

#if defined(__cpp_concepts)

/**
* Concept to restrict a parameter to instantiation of a given template.
* NOTE: this only works with type template parameters.
*/
template <typename T, template <typename...> class Templ>
concept instantiation_of = is_instantiation_of_v<Templ, std::remove_cvref_t<T>>;

#endif

/// member_pointer_traits
///
/// For a member-pointer, reveals its constituent member-type and object-type.
Expand Down Expand Up @@ -301,6 +314,23 @@ struct like {
using type = like_t<Src, Dst>;
};

#if defined(__cpp_concepts)

/**
* Concept to check that a type is same as a given type,
* when stripping qualifiers and refernces.
* Especially useful for perfect forwarding of a specific type.
*
* Example:
* ```
* void foo(folly::any_cvref<std::vector<int>> auto&& vec);
* ```
*/
template <typename Ref, typename To>
concept any_cvref = std::is_same_v<std::remove_cvref_t<Ref>, To>;

#endif

/**
* type_t
*
Expand Down
4 changes: 0 additions & 4 deletions folly/test/PortabilityTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,3 @@ TEST(Portability, Final) {
EXPECT_EQ(3, fooBase(p.get()));
EXPECT_EQ(3, fooDerived(p.get()));
}

#if __has_include(<range>)
static_assert(std::ranges::random_access_range<std::vector<int>>);
#endif
35 changes: 35 additions & 0 deletions folly/test/TraitsTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,26 @@ TEST(Traits, like) {
value));
}

#if defined(__cpp_concepts)
TEST(Traits, AnyCVRef) {
static_assert(folly::any_cvref<std::vector<int>, std::vector<int>>);
static_assert(folly::any_cvref<std::vector<int>&, std::vector<int>>);
static_assert(folly::any_cvref<const std::vector<int>&, std::vector<int>>);
static_assert(folly::any_cvref<std::vector<int>&&, std::vector<int>>);

constexpr auto refersToExample =
[](folly::any_cvref<std::vector<int>> auto&&) {};

static_assert(std::invocable<decltype(refersToExample), std::vector<int>>);
static_assert(
std::invocable<decltype(refersToExample), const std::vector<int>&>);
static_assert(std::invocable<decltype(refersToExample), std::vector<int>&&>);

static_assert(
!std::invocable<decltype(refersToExample), std::vector<char>&&>);
}
#endif

TEST(Traits, isUnboundedArrayV) {
EXPECT_FALSE((folly::is_unbounded_array_v<void>));
EXPECT_FALSE((folly::is_unbounded_array_v<int>));
Expand All @@ -556,6 +576,21 @@ TEST(Traits, isInstantiationOf) {
EXPECT_FALSE((is_instantiation_of<A, B>::value));
}

#if defined(__cpp_concepts)
TEST(Traits, InstantiationOf) {
static_assert(folly::instantiation_of<A<int>, A>);
static_assert(folly::instantiation_of<A<int>&, A>);
static_assert(!folly::instantiation_of<A<int>&, std::vector>);

auto example = [](folly::instantiation_of<std::vector> auto&&) {};

static_assert(std::invocable<decltype(example), std::vector<int>&&>);
static_assert(std::invocable<decltype(example), std::vector<int>&>);
static_assert(std::invocable<decltype(example), const std::vector<int>&>);
static_assert(std::invocable<decltype(example), std::vector<int>>);
}
#endif

TEST(Traits, member_pointer_traits_data) {
struct o {};
using d = float;
Expand Down

0 comments on commit e689e2e

Please sign in to comment.