On 9/28/15 4:25 PM, Atila Neves wrote:
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?
Yes. I also prefer that the compiler do this. I've definitely run into
this before: http://forum.dlang.org/post/[email protected]
-Steve