On 26.06.20 15:09, Johannes Loher wrote:
import std.meta : allSatisfy, staticMap;
import std.traits : allSameType;
import std.range : isInputRange, ElementType, empty;
[...]
@property bool empty(TypeArgs...)(auto ref scope SumType!(TypeArgs) r)
if (allSatisfy!(isInputRange, TypeArgs) && TypeArgs.length > 0)
{
return r.match!(staticMap!(EmptyLambda, TypeArgs));
}
[...]
enum bool myIsInputRange(R) =
is(typeof(R.init) == R)
&& is(ReturnType!((R r) => r.empty) == bool)
&& is(typeof((return ref R r) => r.front))
&& !is(ReturnType!((R r) => r.front) == void)
&& is(typeof((R r) => r.popFront));
void main() {
[...]
import std.traits : ReturnType;
[...]
alias R = SumType!(typeof(i), typeof(o));
// all individual conditions of `isInputRange` are satisfied
static assert(is(typeof(R.init) == R));
static assert(is(ReturnType!((R r) => r.empty) == bool));
[...]
// but `isInputRange` is not satisfied
static assert(!isInputRange!(R));
// and neither is a local copy
static assert(!myIsInputRange!(R));
}
`isInputRange!R` fails because it has no knowledge of your free `empty`
function. Without `empty`, `R` is obviously not a range.
`myIsInputRange!R` fails because you forgot to import `ReturnType` in
module scope. You're importing it locally in `main`, so the check passes
there.