On Tuesday, 16 May 2017 at 12:27:30 UTC, Steven Schveighoffer wrote:

When we have tests using dummy lambdas, are we to expect users to immediately extract the lambda body, parse it, and figure out what's wrong?

This is what you have to do today. The task has already been tried by the compiler, and the result is known by the compiler. Just have the compiler tell you.

:) The compiler does not know what I'm checking for with that lambda. As far as the compiler is concerned, I'm interested in whether it compiles or not. It doesn't care what that means in the context of my constraint. Neither should the user.

The compiler, and by extension your hand-written error checking, cannot know the true intention of the user.

The constraint *is* hand-written error checking. What I'm talking about is hand-written human-readable error messages :) It's not about knowing user intentions, it's about informing them why they made a mistake.

All it knows is you tried to do something that isn't supported. You have to figure out what is wrong and fix it. If that takes several iterations, that's what it takes. There is no solution that will give you all the answers.

Hold on a second, I think there's a mixup in terminology here. A user (caller) of move() is not supposed to be interested in what particular evaluation chain caused the constraint to be false. I, as an author, declare a contract (constraint). I am not interested in user's intentions. I am interested that I'm being called correctly. When the user violates the contract, I must inform them they did so, by reporting *why* their argument does not satisfy me. Not by telling *how* I figured that out (compiler output), but by telling *what* is wrong with the argument (human-readable error message).

If the user does want to know how the constraint caught their mistake, they're free to inspect what the compiler outputs.

That is why (static) asserts have an optional string argument: to display a clean an readable error message, instead of just dumping some code on the user. The same thing, in my opinion, is needed for constraints.

In your example, the compiler would point at isMovable!S as the issue. Not super-informative, but is all it gives to prevent huge outputs. Then you tell it to print more information, and it would say that false was returned when the m member of type T is being checked, at which point you could get a stack trace of what values were at each level of recursion. Everywhere a boolean evaluated to true in order to get to the point where false is returned would be colored green, every time it was false, it would be colored red, and every time a short circuit happened, it wouldn't be colored.

Or the user could just read a string "This overload cannot be called, because argument 1 (struct S) has a destructor and non-statically initialized const members". No "then", no printing more information, no stack traces. User is informed their type is wrong and *why* it is wrong. If they disagree, if they think there's a bug in the constraint, or if they're interested in how the constraint works, they're free to go through all the hoops you describe.

We can't hand-hold everyone. At some point you have to learn programming and debugging :)

It's not about hand-holding. If I call a function from a foreign API, and the call does not compile, I'd want to know why it didn't compile, not what the author of the API did to make it not compile. I'd want to know what *I* must do to make it compile. Preferably without dissecting the API in order to find that out.

Reply via email to