On Wednesday, 29 April 2020 at 09:16:58 UTC, user1234 wrote:
The static checker doesn't see your free funcs because to do so
it would have to import the whole module. (is it possible to do
that ? no idea.)
Of course it's possible! :) We can find the context of R (in this
case, the module) with __traits(parent), and import that:
mixin("import "~__traits(parent, R).stringof["module
".length..$]~";");
However, doing that in isInputRange doesn't help much. First, all
other range functions would have to do it, and second, just
importing into function scope doesn't enable UFCS lookup.
Also your signature for the primitives are quite unusual (i.e
not idiomatic). Usually they dont take param. Usually we pass a
type that contains the member funcs matching to IsIntputRange.
You can see a good counterexample to this in
https://dlang.org/library/std/range/primitives/pop_front.html,
which defines popFront for regular arrays. However, that is the
one and only counterexample I know of.
Of course, nothing stops us from defining our own front, popFront
and friends that combine the two approaches above:
template front(R) {
auto front(R r) {
return __traits(getMember, __traits(parent, R),
"front")(r);
}
}
template popFront(R) {
auto popFront(R r) {
return __traits(getMember, __traits(parent, R),
"popFront")(r);
}
}
template empty(R) {
auto empty(R r) {
return __traits(getMember, __traits(parent, R),
"empty")(r);
}
}
We could conceivably add these to std.range.primitives (probably
adding some constraints first), and suddenly UFCS ranges are
possible! (I am as of yet not convinced that we should, though)
--
Simen