Search code examples
c++templatestype-traits

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


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?


Solution

  • 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;