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 && ...);
}