Reputation: 13752
Is there an already defined concept for specifying a range of a specific type, in C++20 or in the ranges-TS?
Something like:
template < class T, class InnerType >
concept RangeOf =
requires(T&& t) {
requires std::same_as<
std::remove_cvref_t<decltype(*std::ranges::begin(t))>,
InnerType
>;
std::ranges::end(t);
};
To allow, for example:
void print(const RangeOf<char> auto& char_seq) { /* ... */ }
Upvotes: 19
Views: 3665
Reputation: 302748
No there isn't.
The way to spell that particular concept would be:
template <typename R, typename V>
concept RangeOf = range<R> && same_as<range_value_t<R>, V>;
But then it turns out there's a bunch of very closely related things you might want to check as well. You might actually want to look at the reference
type rather than the value_type
. Perhaps that's:
template <typename R, typename V>
concept RangeOf = range<R> && same_as<range_reference_t<R>, V>;
The reason is: do you consider vector<char>&
to be a range of char
or a range of char&
? Arguably, it's more like the latter, and it's the latter that drives a lot more usage. But it's not that the former is wrong; it's useful too, just in a different way.
Then you have to talk about whether you want same_as
or convertible_to
. There are some algorithms in which you would want to restrict to the former, and some in which the latter is good enough.
This issue of same_as
vs convertible_to
, to me, is one of the motivating reasons for wanting concept template parameters, so that:
template <typename R, template <typename> concept C>
concept RangeOf = range<R> && C<range_value_t<R>>;
So that I can easily write RangeOf<same_as<char>>
or RangeOf<convertible_to<char>>
, depending on what I actually want. However, this brings up other parsing issues too (if RangeOf
takes a unary concept, how do you make same_as<char>
- which is not a unary concept but rather a partially applied concept that is not valid in all contexts - work?) so it's unclear how to really make this work. There's currently a proposal for this, but it would not actually handle this use-case especially well (largely because it's not actually clear how to handle this use-case especially well).
All of which is to say, it's hard to know what actual thing we would want for RangeOf
, which is why no such thing exists. But each specific thing that would be useful is very easy to write, so the lack of such a thing isn't a especially large burden on the user.
Upvotes: 26