Home > Back-end >  How can I check if the type `T` is `std::pair<?, bool>` in C ?
How can I check if the type `T` is `std::pair<?, bool>` in C ?

Time:08-08

We can define a function to insert multiple values to a set like this:

template <typename T, typename... U>
bool insert_all(T& to, const U... arguments) {

    return (to.insert(arguments).second && ...);
}

So this code can insert 4, 5 and 6 to the set:

std::set set { 1, 2, 3 };
insert_all(set, 4, 5, 6);

Obviously, type T maybe a type without a method accepting int, called insert and returns std::pair<?, bool>. It's necessary to check it by SFINAE:

template <typename T, typename U, typename = void>
struct can_insert : std::false_type {
};

template <typename T, typename U>
struct can_insert<T, U, 
    std::enable_if_t<std::is_same_v<decltype(std::declval<T>().insert(std::declval<U>())), std::pair<typename T::iterator, bool>>, void>
> : std::true_type {
};

template <typename T, typename U>
inline constexpr auto can_insert_v = can_insert<T, U>::value;

Pay attention to the second one, ...std::pair<typename T::iterator, bool>>..., how to express it like java code ? extends Pair<?, Boolean> gracefully?

CodePudding user response:

It's not much different than the technique you already coded:

#include <tuple>
#include <type_traits>

template<typename T>
struct is_pair_t_and_bool : std::false_type {};

template<typename T>
struct is_pair_t_and_bool<std::pair<T, bool>> : std::true_type {};

static_assert( is_pair_t_and_bool<std::pair<char, bool>>::value );

static_assert( !is_pair_t_and_bool<int>::value );
static_assert( !is_pair_t_and_bool<std::pair<int, int>>::value );

And, in C 20, once you've gone that far you might as well make it a concept:

template<typename T>
concept pair_t_and_bool=is_pair_t_and_bool<T>::value;

template<pair_t_and_bool T>
struct something {};

something<std::pair<int, bool>> this_compiles;
something<std::pair<int, int >> this_doesnt_compile;

CodePudding user response:

With the help of C 20 concepts, you can define can_insert as concept like:

template<class T, class U>
concept can_insert = std::ranges::range<T> &&
  requires(T& to, const U argument) {
    { to.insert(argument) } -> 
      std::same_as<std::pair<std::ranges::iterator_t<T>, bool>>;
};

Then use it to constrain insert_all like

template<typename T, typename... U>
  requires (can_insert<T, U> && ...)
bool insert_all(T& to, const U... arguments) {
  return (to.insert(arguments).second && ...);
}
  • Related