xxxxxxxxxx
import std.stdio;
void main()
{
import std.range.primitives : isInputRange;
import std.traits : ReturnType;
// This code is taken from the implementation of isInputRange, with the
// type parameter R being replaced by NoRange and the assertion split up
// for easier debugging.
// This works.
assert(is(typeof(NoRange.init) == NoRange));
assert(is(ReturnType!((NoRange r) => r.empty) == bool));
assert(is(typeof((return ref NoRange r) => r.front)));
assert(!is(ReturnType!((NoRange r) => r.front) == void));
assert(is(typeof((NoRange r) => r.popFront)));
// This doesn't.
//assert(isInputRange!NoRange);
// Note that the latter is actually derived from
// enum bool isInputRange(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));
auto nr = NoRange(10);
foreach(i; nr) { writeln(i); }
}
private struct NoRange {
this (int maxValue)
in {
assert(maxValue >=0);
}
do
{
this.maxValue = maxValue;
}
int front() { return currentValue; }
private int maxValue;
private int currentValue;
}
private bool empty(NoRange noRange) {
return noRange.currentValue >= noRange.maxValue;
}
private void popFront(ref NoRange noRange) {
noRange.currentValue++;
}
private int front(NoRange noRange) {
return noRange.currentValue;
}