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.

Reply via email to