On Friday, 31 July 2015 at 14:24:58 UTC, Atila Neves wrote:
Notice however, that (again, in the PR), the "real" definition
happens only once, in the check function. Then the constraint
is always a trivial `enum MyConstraint =
is(typeof(myCheckFunction));`. It's just a matter of moving the
lambda away, giving it a name, and doing the weird
`if(!__ctfe)` hack.
Atila
Looking at the PR also resolved my earlier question. Running the
code as below (do not import std.range) will tell you exactly
what isn't implemented from isInputRange (in this case, I
commented out popFront). Very cool.
template satisfies(alias Constraint, R) {
enum check = "check" ~ Constraint.stringof[2..$-3] ~ "!(R)";
enum assert_ = "static assert("~ check ~ ");";
mixin(assert_); //mixes in "static assert(checkInputRange!R)"
}
template isInputRange(R)
{
enum bool isInputRange = is(typeof(checkInputRange!R));
}
bool checkInputRange(R)(inout int = 0)
{
if (__ctfe)
{
R r = R.init; // can define a range object
if (r.empty) {} // can test for empty
r.popFront(); // can invoke popFront()
auto h = r.front; // can get the front of the range
}
return true;
}
@satisfies!(isInputRange, Zeroes)
struct Zeroes {
enum empty = false;
//void popFront() {}
@property int front() { return 0; }
}
void main()
{
Zeroes Z;
}