The problem here is: what is the actual constraint that you want?
Do you want to:
- constrain on the range's value type being specifically
T
?
- constrain on the range's value type being convertible to
T
?
- constrain on the range's value type satisfying some other concept,
C
?
- any of the above but instead about the range's reference type?
Different contexts call for different versions of this. Your range_of
concept is a perfectly fine implementation of the first one of these (could use std::same_as
instead of std::is_same_v
but doesn't super matter). But what happens when you want something else? The specific choice of constraint is going to depend very much on what it is you want to do.
So the direct answer is: there's no range_of
concept because there's really no one true answer of what that concept should do.
A different answer would be that this isn't even what would be useful. What would be useful would be a direct way to pull out the associated types of a given range
to make it easy to add further constraints on them.
For instance, if we take Rust, we can define a function that takes an arbitrary iterator:
fn foo<I: Iterator>(it: I) { ... }
That's sort of akin to just void f(range auto)
. It's a constraint, but not a very useful one. But Iterator
, in Rust, has an associated type: its Item
. So if you wanted an Iterator
over a specific type, that's:
fn foo<I: Iterator<Item=i32>>(it: I) { ... }
If you wanted an Iterator
whose type satisfies some other constraint:
fn foo<T: Debug, I: Iterator<Item=T>>(it: I) { ... }
And it's really this ability - to pull out associated types and constrain on them directly - that we really lack.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…