Skip to content

Commit

Permalink
Traits: add is_pairish_of_v type trait
Browse files Browse the repository at this point in the history
The trait allows to check if the type is a pair-like object, containing
objects of two particular types.
  • Loading branch information
drewdzzz committed Nov 28, 2023
1 parent 0aad721 commit 9a2ecb0
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 0 deletions.
19 changes: 19 additions & 0 deletions src/Utils/Traits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
* tuple_iseq
* is_tuplish_v (standard (tuple, array, pair) + bounded array)
* is_pairish_v
* is_pairish_of_v
* is_tuplish_of_pairish_v
* is_variant_v
* is_optional_v
Expand Down Expand Up @@ -489,6 +490,24 @@ struct is_pairish_h<T, std::void_t<
template <class T>
constexpr bool is_pairish_v = details::is_pairish_h<std::remove_cv_t<T>>::value;

namespace details {
template <class T, class V1, class V2, class _ = void>
struct is_pairish_of_h : std::false_type {};

template <class T, class V1, class V2>
struct is_pairish_of_h<T, V1, V2, std::void_t<
std::enable_if_t<is_pairish_v<T>, void>,
std::enable_if_t<std::is_same_v<std::remove_cv_t<decltype(std::declval<T&>().first)>, V1>, void>,
std::enable_if_t<std::is_same_v<std::remove_cv_t<decltype(std::declval<T&>().second)>, V2>, void>>>
: std::true_type {};
} //namespace details {

template <class T, class V1, class V2>
constexpr bool is_pairish_of_v = details::is_pairish_of_h<
std::remove_cv_t<T>,
std::remove_cv_t<V1>,
std::remove_cv_t<V2>>::value;

/**
* Check whether the type is compatible with std::tuple (see is_tuplish_v) and
* consist of types that are compatible with std::pair (see is_pairish_v).
Expand Down
18 changes: 18 additions & 0 deletions test/TraitsUnitTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,24 @@ test_tuple_pair_traits()
static_assert(!tnt::is_pairish_v<Test>);
static_assert(!tnt::is_pairish_v<const_int>);

static_assert(tnt::is_pairish_of_v<std::pair<int, bool>, int, bool>);
static_assert(!tnt::is_pairish_of_v<std::pair<int, bool>, bool, int>);
static_assert(!tnt::is_pairish_of_v<std::pair<int, bool>, int, char>);
static_assert(!tnt::is_pairish_of_v<std::pair<int, bool>, char, bool>);
static_assert(tnt::is_pairish_of_v<const volatile std::pair<int, int>, int, int>);
static_assert(tnt::is_pairish_of_v<std::pair<int&, float&&>, int&, float&&>);
static_assert(!tnt::is_pairish_of_v<const std::pair<int, int>&, int, int>);
static_assert(tnt::is_pairish_of_v<CustomPair, int, double>);
static_assert(tnt::is_pairish_of_v<const CustomPair, int, double>);
static_assert(!tnt::is_pairish_of_v<const CustomPair&, int, double>);

static_assert(!tnt::is_pairish_of_v<TupleClass, int, float>);
static_assert(!tnt::is_pairish_of_v<std::tuple<int, int>, int, int>);
static_assert(!tnt::is_pairish_of_v<Test, int, int>);
static_assert(!tnt::is_pairish_of_v<int, int, int>);
static_assert(!tnt::is_pairish_of_v<E, int, int>);
static_assert(!tnt::is_pairish_of_v<const_int, int, int>);

static_assert(tnt::is_tuplish_of_pairish_v<std::tuple<>>);
static_assert(!tnt::is_tuplish_of_pairish_v<std::tuple<int>>);
static_assert(tnt::is_tuplish_of_pairish_v<std::tuple<std::pair<int, int>>>);
Expand Down

0 comments on commit 9a2ecb0

Please sign in to comment.