Comment #0 by qs.il.paperinik — 2023-10-24T15:32:43Z
This is from the first question of [DConf '23 Day 2 Keynote](https://youtu.be/3iWn4S8JV8g?t=2323): How do I communicate to the user of a function template that the return type is a range?
The compiler has all it needs to check it (per template instance). We just cannot express it with D’s syntax.
I see two solutions:
SOLUTION 1: Make template `if` constraints work with `typeof(return)` even if it’s inferred by deferring the constraint check.
SOLUTION 2: Introduce a new kind of template constraint that’s checked after instantiation, a template `assert`.
I’d guess that Solution 2 is easier to implement and communicates better. I like both solutions, tho.
## Solution 1
I have no idea how templates are compiled and how their constraints are checked, but I’ll assume the constraints are checked before the body is instantiated.
Of course if `typeof(return)` targets an inferred return type, it cannot be checked before instantiating the template.
Because a template constraint is a logical expression tree composed of `&&`s, `||`s and `!`s and other expressions as leafs, I’d imagine it like this:
1. Leaves that contain `typeof(return)` are pretended to be `true` if the leaf is under an even number of negations, otherwise `false`. (They’re essentially skipped.)
2. Then the template is instantiated. If there were `typeof(return)` in step 1, errors are throttled.
3. If the template has constraints with `typeof(return)` (that were skipped), now that the return type is known, the constraints are checked again. (Constraints without `typeof(return)` could be pretended `true` or `false` as above.) If the constraint evaluates to `true`, there were `typeof(return)` in step 1, and throttled errors in step 2, then report the errors of step 2.
For the most part, constraints will look like this:
```d
auto someAlgo(R)(R range)
if (isInputRange!R && isInputRange!(typeof(return)))
{ … }
```
## Solution 2
An alternative would be a new construct next to template constraints. I suggest `assert`; while constraints are checked as one of the first steps of template instantiation, template `assert`s would be checked as one of the last steps (at a point the return type is successfully inferred).
```d
auto someAlgo(R)(R range)
if (isInputRange!R)
assert (isInputRange!(typeof(return)))
{ … }
```
The template `assert` would be essentially a `static assert` the same way a template `if` constraint essentially is a `static if`.
Template `if` and template `assert` are the compile-time/static analogue of runtime `in` and `out` function contracts.
Comment #1 by qs.il.paperinik — 2023-10-24T15:44:02Z
This can be done (in a limited extent) in C++20:
```cpp
#include <concepts>
template<std::integral T>
std::integral auto f(T t)
{
return t + 1;
}
```
Comment #2 by b2.temp — 2023-10-24T16:56:45Z
You'll find an alternative syntax idea in https://issues.dlang.org/show_bug.cgi?id=20595. For the functionality in itself, comment #1 suggested to use a static assert in an `out` contract.
Comment #3 by robert.schadek — 2024-12-13T19:31:17Z