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;
}

Reply via email to