I've mentioned this many times before: template constraints are like unittest blocks with asserts in D: great that they're built-in easy to use. But when they fail, there's no help in figuring out why.

I've had many a debugging session (with pragma(msg) of course, since my bugs were of the compile-time variety and there's no debugger for that) due to failing to satisfy a template constraint that I thought I'd implemented the correct functions for. It'd be nice if the compiler told me why. I did a PR a while back with an idea from Adam's book but it didn't work in the context of Phobos and interfaces. I've come up with a PR (https://github.com/D-Programming-Language/phobos/pull/3677) that will let users type this:

    @models!(MyStruct, isInputRange)
    struct MyStruct { ... }

Or this:

    struct MyStruct {
        ...
        static assert(models!(MyStruct, isInputRange));
    }

When the template constraint isn't satisfied, the compiler will dutifully tell you why. The only requirement is that there be a checkXXX function for an isXXX template constraint. I've updated the original PR for `isInputRange` to make the above code possible. I chose the name `models` because I just got back from CppCon and concepts might have tainted my brain. It's unfortunate to have to specify the type in the UDA version, but it's what the language as it is now will allow me to do.

I created an input range, verified it compiled, then added a 't' to the end of `front`. With `models` I got this for both UDA and static assert versions:

/home/atila/coding/d/dlang/phobos/std/range/primitives.d(182): Error: template std.range.primitives.front cannot deduce function from argument types !()(Foo), candidates are: /home/atila/coding/d/dlang/phobos/std/range/primitives.d(2219): std.range.primitives.front(T)(T[] a) if (!isNarrowString!(T[]) && !is(T[] == void[])) /home/atila/coding/d/dlang/phobos/std/range/primitives.d(2247): std.range.primitives.front(T)(T[] a) if (isNarrowString!(T[])) /home/atila/coding/d/dlang/phobos/std/traits.d-mixin-6771(6771): Error: template instance std.range.primitives.checkInputRange!(Foo) error instantiating concepts.d(81): instantiated from here: models!(Foo, isInputRange) Failed: ["dmd", "-unittest", "-main", "-v", "-o-", "concepts.d", "-I."]


With `static assert(isInputRange!Foo)`, I get this:

concepts.d(87): Error: static assert (isInputRange!(Foo)) is false Failed: ["dmd", "-unittest", "-main", "-v", "-o-", "concepts.d", "-I."]

I prefer the first one. How about you?

Atila


Reply via email to