On Friday, 31 July 2015 at 14:23:28 UTC, Atila Neves wrote:
On Friday, 31 July 2015 at 11:16:48 UTC, Biotronic wrote:
On Thursday, 30 July 2015 at 10:40:59 UTC, Atila Neves wrote:
[...]
Why are there two different things in the first place?
@satisfies!(myConcept, T) should test the constraints and give
a sensible error message. This you use to indicate that type T
implements myConcept.
Why can't another template use the very same concept
information to check if a type implements the concept?
e.g.:
@satisfies!(myConcept, MyStruct)
struct MyStruct { /* ... */ }
void foo(T)(T t) if (check!(myConcept, T))
{ /* ... */ }
Because you want to:
1. Check your type and get sensible error messages
2. Use a constraint in function declarations
You can't have `@satisfies!(isInputRange, T)` give you an error
message if it doesn't have access to the source code of the
lambda that actually does the checking and you can't get error
messages unless you force the compilation of code you _know_
won't compile.
It's ok for template constraints to be false without causing a
compilation error; that's how we get compile-time template
function resolution. When you're using something like
`@satisfies` however, you want a compilation error and its
message. That's why you need two things.
Atila
Notice however, that (again, in the PR), the "real" definition
happens only once, in the check function. Then the constraint is
always a trivial `enum MyConstraint =
is(typeof(myCheckFunction));`. It's just a matter of moving the
lambda away, giving it a name, and doing the weird `if(!__ctfe)`
hack.
Atila