Skip to content

Commit d2c6cb3

Browse files
committed
Add some docs for constrained deduced parameter/local object types
1 parent 72b9833 commit d2c6cb3

File tree

4 files changed

+28
-10
lines changed

4 files changed

+28
-10
lines changed

docs/cpp2/common.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ The operators `.`, `..`, `*`, `&`, `~`, `++`, `--`, `()`, `[]`, `...`, `..=`, an
202202

203203
Postfix notation lets the code read fluidly left-to-right, in the same order in which the operators will be applied, and lets declaration syntax be consistent with usage syntax. For more details, see [Design note: Postfix operators](https://github.com/hsutter/cppfront/wiki/Design-note%3A-Postfix-operators).
204204

205-
> Note: The function call syntax `f(x)` calls a namespace-scope function, or a function object, named `f`. The function call syntax `x.f()` is a unified function call syntax (aka UFCS) that calls a type-scope function in the type of `x` if available, otherwise calls the same as `f(x)`. The function call syntax `x..f()` calls a type-scope function only. For details, see [Design note: UFCS](https://github.com/hsutter/cppfront/wiki/Design-note%3A-UFCS).
205+
> Note: The function call syntax `f(x)` calls a namespace-scope function only. The function call syntax `x.f()` is a unified function call syntax (aka UFCS) that calls a type-scope function in the type of `x` if available, otherwise calls the same as `f(x)`. The function call syntax `x..f()` calls a type-scope function only. For details, see [Design note: UFCS](https://github.com/hsutter/cppfront/wiki/Design-note%3A-UFCS).
206206
207207
| Unary operator | Cpp2 example | Cpp1 equivalent |
208208
|---|---|---|
@@ -214,9 +214,9 @@ Postfix notation lets the code read fluidly left-to-right, in the same order in
214214
| `#!cpp --` | `#!cpp iter--` | `#!cpp --iter` |
215215
| `(` `)` | `#!cpp f( 1, 2, 3)` | `#!cpp f( 1, 2, 3)` |
216216
| `[` `]` | `#!cpp vec[123]` | `#!cpp vec[123]` |
217-
| `...` (half-open range operator) | `#!cpp v.begin()...v.end()` | `#!cpp std::ranges::subrange(v.begin(), v.end())` |
218-
| `..=` (closed range operator) | `#!cpp 1..=10` | `#!cpp std::views::iota(1, 11)` |
219-
| `$` (capture operator) | `val$` | _reflection — no Cpp1 equivalent yet_ |
217+
| `...` | `#!cpp v.begin()...v.end()` | `#!cpp std::ranges::subrange(v.begin(), v.end())` |
218+
| `..=` | `#!cpp 1..=10` | `#!cpp std::views::iota(1, 11)` |
219+
| `$` | `val$` | _reflection — no Cpp1 equivalent yet_ |
220220

221221
> Note: The `...` pack expansion syntax is also supported. The above `...` and `..=` are the Cpp2 range operators, which overlap in syntax.
222222

docs/cpp2/expressions.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ A function call like `x.f()` is a unified function call syntax (aka UFCS) call.
1111

1212
An operator notation call like `#!cpp a + b` will call an overloaded operator function if one is available, as usual in C++.
1313

14-
A function call like `x..f()` will consider only member functions.
14+
A function call like `x..f()` will consider member functions only.
1515

1616
For example:
1717

@@ -33,7 +33,7 @@ f: ( v : std::vector<widget> ) = {
3333
// safely using string interpolation (instead of type-unsafe format strings)
3434
hello: (name, height: float) = {
3535
// Using UFCS to make direct calls to C functions as if they were members
36-
stdout.fprintf( "%s", ("Hello (name)$, your height is (height:.1f)$ inches!\n").c_str() );
36+
stdout.fprintf("%s", ("Hi (name)$, your height is (height:.1f)$\"!\n").c_str());
3737
// Equivalent using iostreams:
3838
// std::cout << "Hello (name)$, your height is (height:.1f)$ inches!\n";
3939

@@ -47,9 +47,9 @@ main: () = {
4747
hello("Polyphemus", 180);
4848
}
4949
// Sample output:
50-
// Hello Flimnap, your height is 6.5 inches!
51-
// Hello Goliath, your height is 115.0 inches!
52-
// Hello Polyphemus, your height is 180.0 inches!
50+
// Hi Flimnap, your height is 6.5"!
51+
// Hi Goliath, your height is 115.0"!
52+
// Hi Polyphemus, your height is 180.0"!
5353
```
5454

5555
To explicitly treat an object name passed as an argument as `move` or `out`, write that keyword before the variable name.
@@ -229,7 +229,7 @@ For more examples, see also the examples in the previous two sections on `is` an
229229
230230
For example:
231231
232-
``` cpp title="Using ... and ..= for ranges" hl_lines="4,11"
232+
``` cpp title="Using ... and ..= for ranges" hl_lines="5 11"
233233
test: (v: std::vector<std::string>) =
234234
{
235235
// Print strings from "Nonesuch" (if present) onward

docs/cpp2/functions.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,17 @@ func: (
2727
}
2828
```
2929

30+
The parameter type can be deduced by writing `_` (the default, so it can be omitted). You can use `is` to declare a type constraint (e.g., a concept) that a deduced type must match, in which case `_` is required. For example:
31+
32+
``` cpp title="Declaring a parameter of constrained deduced type" hl_lines="2 3 6"
33+
// ordinary generic function, x's type is deduced
34+
print: (x: _) = { std::cout << x; }
35+
print: (x) = { std::cout << x; } // same, using the _ default
36+
37+
// number's type is deduced, but must match the std::integral concept
38+
calc: (number: _ is std::integral) = { /*...*/ }
39+
```
40+
3041
There are six ways to pass parameters that cover all use cases, that can be written before the parameter name:
3142
3243
| Parameter ***kind*** | "Pass me an `x` I can ______" | Accepts arguments that are | Special semantics | ***kind*** `x: X` Compiles to Cpp1 as |

docs/cpp2/objects.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,13 @@ pi: <T: type> T == 3.14159'26535'89793'23846L;
2929
pi: _ == 3.14159'26535'89793'23846L; // same, deducing the object's type
3030
```
3131

32+
The parameter type can be deduced by writing `_` (the default, so it can be omitted). You can use `is` to declare a type constraint (e.g., a concept) that a deduced type must match, in which case `_` is required. For example:
33+
34+
``` cpp title="Declaring an object of constrained deduced type" hl_lines="2"
35+
// number's type is deduced, but must match the std::regular concept
36+
number: _ is std::regular = some_factory_function();
37+
```
38+
3239

3340
## <a id="init"></a> Guaranteed initialization
3441

0 commit comments

Comments
 (0)