On Saturday, 14 February 2015 at 17:00:33 UTC, Andrei
Alexandrescu wrote:
There's been recurring discussion about failing constraints not
generating nice error messages.
void fun(T)(T x) if (complicated_condition) { ... }
struct Type(T)(T x) if (complicated_condition) { ... }
If complicated_condition is not met, the symbol simply
disappears and the compiler error message just lists is as a
possible, but not viable, candidate.
I think one simple step toward improving things is pushing the
condition in a static_assert inside type definitions:
void fun(T)(T x) if (complicated_condition) { ... } // no change
struct Type(T)(T x)
{
static assert(complicated_condition, "Informative message.");
...
}
This should improve error messages for types (only). The
rationale is that it's okay for types to refuse compilation
because types, unlike functions, don't overload. The major
reason for template constraints in functions is allowing for
good overloading.
Andrei
I've done this myself for the same reason. I may split up the
condition into multiple 'static assert' statements which gives a
more specific error message. However, I wonder if there's a
better solution that we can incorporate in to D. The trouble with
template constraints is that, if you have complex conditions,
there's no easy way to fall back to a default state. You would
have to duplicate all the conditions and write "not this and not
this and not this and ...".
Template specializations can fall back to a default state, but
not template constraints. So what if we were to add a feature
that would allow us to do just that?
void test(Range)(Range r) if(isRandomAccessRange!Range)
{
...
}
void test(Range)(Range r) default
{
static assert(false, "descriptive error message");
}
I'm not claiming this is a better solution; I'm simply putting
the idea out there.