User-defined template error messages
luckoverthere
luckoverthere at gmail.cm
Sun Jan 13 19:38:01 UTC 2019
On Sunday, 13 January 2019 at 18:54:52 UTC, Andrei Alexandrescu
wrote:
> We've had this problem for a long time - template doesn't match
> because of a complex constraint, the error message is
> unhelpful, and the user doesn't know what to do.
>
> I think this is an important missed opportunity. One of the
> promises of Design by Introspection is it raises the level of
> error messages from mere built-in canned messages to
> higher-level messages expressed in terms of problem-space
> entities.
>
> A simple way to address this would be with a two-pronged
> proposal:
>
> 1. Allow multiple "if" constraints in a template. All "if"
> constraints must match. This means a natural way to write
> complex constraints is a conjunction of simpler constraints.
>
> 2. Extend the syntax to:
>
> if (condition) else string
>
> The string (which crucially can be a CT expression involving
> template parameters) is the error message that would be
> displayed should the condition be false.
>
> When an overload set is being looked up, if no match then the
> string corresponding to the first failed condition in each
> overload is printed as the error message.
>
> Example from std. Current sig:
>
> InputRange2 moveAll(InputRange1, InputRange2)(InputRange1 src,
> InputRange2 tgt)
> if (isInputRange!InputRange1 && isInputRange!InputRange2
> && is(typeof(move(src.front, tgt.front))));
>
> With the proposal:
>
> InputRange2 moveAll(InputRange1, InputRange2)(InputRange1 src,
> InputRange2 tgt)
> if (isInputRange!InputRange1)
> else InputRange1.stringof ~ " must be an input range"
> if (isInputRange!InputRange2)
> else InputRange2.stringof ~ " must be an input range"
> if (is(typeof(move(src.front, tgt.front))))
> else "Cannot move from the front of "~InputRange1.stringof~
> " to the front of "~InputRange2.stringof;
>
> Larger but offers the benefits of beautiful error messages.
>
>
> Andrei
I don't really like that syntax, it changes the meaning of what
if/else mean and how they behave from everything else.
This makes more sense logically and is in line with how if/else
functions. Though still not 100% accurate as the else should
technically be with the last if statement.
InputRange2 moveAll(InputRange1, InputRange2)(InputRange1 src,
InputRange2 tgt)
if (!isInputRange!InputRange1) InputRange1.stringof ~ " must be
an input range"
if (!isInputRange!InputRange2) InputRange2.stringof ~ " must be
an input range"
if (!is(typeof(move(src.front, tgt.front))))
"Cannot move from the front of "~InputRange1.stringof~
" to the front of "~InputRange2.stringof;
else
{
// implementation ...
}
Still this sort of syntax only really works well if the statement
is expressed using &&'s but you can't reduce it if you need ||
logic. All of the || logic would need to be in the same if
statement. Then determining which condition was false would
require addition if statements to provide a proper message.
We could just go with something like what is being done with
asserts.
> InputRange2 moveAll(InputRange1, InputRange2)(InputRange1 src,
> InputRange2 tgt)
> if (isInputRange!InputRange1 && isInputRange!InputRange2
> && is(typeof(move(src.front, tgt.front))));
For the above case detect what part of the if statement failed.
The error message would be something like
<function declaration>
Arguments don't match as isInputRange!TheRangeTypeUsed is false.
More information about the Digitalmars-d
mailing list