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

Reply via email to