Skip to content

Commit 74fb716

Browse files
committed
Add requires, namespaces, using, and namespace/type/function/object aliases
1 parent b795f31 commit 74fb716

File tree

3 files changed

+162
-19
lines changed

3 files changed

+162
-19
lines changed

docs/cpp2/aliases.md

Lines changed: 82 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,97 @@
11
# Aliases
22

3+
Aliases are pronounced **"synonym for**, and written using the same **name `:` kind `=` value** [declaration syntax](../cpp2/declarations.md) as everything in Cpp2:
4+
5+
- **name** is declared to be a synonym for **value**.
6+
7+
- **kind** can be any of the kinds: `namespace`, `type`, a function signature, or a type.
8+
9+
- **`==`**, pronounced **"defined as a synonym for"**, always precedes the value. The `==` syntax stresses that during compilation every use of the name could be equivalently replaced with the value.
10+
11+
- **value** is the expression that the **name** is a synonym for.
12+
13+
314
## <a id="namespace-aliases"></a> Namespace aliases
415

5-
TODO
16+
A namespace alias is written the same way as a [namespace](namespaces.md), but using `==` and with the name of another namespace as its value. For example:
17+
18+
``` cpp title="Namespace aliases" hl_lines="1 2 4 5 8 12 16"
19+
// 'chr' is a namespace defined as a synonym for 'std::chrono'
20+
chr : namespace == std::chrono;
21+
22+
// 'chrlit' is a namespace defined as a synonym for 'std::chrono_literals'
23+
chrlit : namespace == std::chrono_literals;
24+
25+
main: () = {
26+
using namespace chrlit;
27+
28+
// The next two lines are equivalent
29+
std::cout << "1s is (std::chrono::nanoseconds(1s).count())$ns\n";
30+
std::cout << "1s is (chr::nanoseconds(1s).count())$ns\n";
31+
}
32+
// Prints:
33+
// 1s is 1000000000ns
34+
// 1s is 1000000000ns
35+
```
36+
637

738
## <a id="type-aliases"></a> Type aliases
839

9-
TODO
40+
A namespace alias is written the same way as a [type](types.md), but using `==` and with the name of another type as its value. For example:
41+
42+
``` cpp title="Type aliases" hl_lines="1 2 7 10"
43+
// 'imap<T>' is a type defined as a synonym for 'std::map<i32, T>'
44+
imap : <T> type == std::map<i32, T>;
45+
46+
main: () = {
47+
// The next two lines declare two objects with identical type
48+
map1: std::map<i32, std::string> = ();
49+
map2: imap<std::string> = ();
50+
51+
// Assertion they are the same type, using the same_as concept
52+
assert( std::same_as< decltype(map1), decltype(map2) > );
53+
}
54+
```
55+
1056

1157
## <a id="function-aliases"></a> Function aliases
1258

13-
TODO
59+
A function alias is written the same way as a [function](functions.md), but using `==` and with a side-effect-free body as its value; the body must always return the same value for the same input arguments. For example:
60+
61+
``` cpp title="Function aliases" hl_lines="1 2 6 9 12 15"
62+
// 'square' is a function defined as a synonym for the value of 'i * i'
63+
square: (i: i32) -> _ == i * i;
64+
65+
main: () = {
66+
// It can be used at compile time, with compile time values
67+
ints: std::array<i32, square(4)> = ();
68+
69+
// Assertion that the size is the square of 4
70+
assert( ints.size() == 16 );
71+
72+
// And if can be used at run time, with run time values
73+
std::cout << "the square of 4 is (square(4))$\n";
74+
}
75+
// Prints:
76+
// the square of 4 is 16
77+
```
78+
79+
> Note: A function alias is compiled to a Cpp1 `#!cpp constexpr` function.
80+
1481

1582
## <a id="object-aliases"></a> Object aliases
1683

17-
TODO
84+
An object alias is written the same way as an [object](objects.md), but using `==` and with a side-effect-free value. For example:
85+
86+
``` cpp title="Function aliases" hl_lines="1 2 5 6"
87+
// 'BufferSize' is an object defined as a synonym for the value 1'000'000
88+
BufferSize: i32 == 1'000'000;
89+
90+
main: () = {
91+
buf: std::array<std::byte, BufferSize> = ();
92+
assert( buf.size() == BufferSize );
93+
}
94+
```
1895

96+
> Note: An object alias is compiled to a Cpp1 `#!cpp constexpr` object.
1997

docs/cpp2/declarations.md

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,23 @@
44

55
All Cpp2 declarations are written as **"_name_ `:` _kind_ `=` _statement_"**.
66

7+
- The _name_ must be a valid identifier (start with a letter, and consist of letters, digits, or `_`). The name can be variadic (be a name for a list of zero or more things) by writing a `...` suffix at the end of the name.
8+
79
- The `:` is pronounced **"is a."**
810

9-
- The _kind_ can start with [template parameters](#template-parameters).
11+
- The _kind_ can start with [template parameters](#template-parameters) and end with [`#!cpp requires` constraints](#requires).
1012

11-
- The `=` is pronounced **"defined as."** For the definition of something that will always have the same value, write `==`.
13+
- The `=` is pronounced **"defined as."** For the definition of something that will always have the same value, write `==`, pronounced **"defined as a synonym for"**.
1214

1315
- The _statement_ is typically an expression statement (e.g., `#!cpp a + b();`) or a compound statement (e.g., `#!cpp { /*...*/ return c(d) / e; }`).
1416

15-
- Various parts of the syntax allow a `_` "don't care" wildcard or can be omitted entirely to accept a default (e.g., `#!cpp x: int = 0;` can be equivalently written `#!cpp x: _ = 0;` or `#!cpp x := 0;` both of which deduce the type).
17+
Various parts of the syntax allow a `_` "don't care" wildcard or can be omitted entirely to accept a default (e.g., `#!cpp x: int = 0;` can be equivalently written `#!cpp x: _ = 0;` or `#!cpp x := 0;` both of which deduce the type).
1618

1719
> Notes:
1820
>
1921
> - When the type is omitted, whitespace does not matter, and writing `#!cpp x: = 0;` or `#!cpp x : = 0;` or `#!cpp x := 0;` or other whitespace is just a stylistic choice. This documentation's style uses the last one, except when there are multiple adjacent declaration lines this style lines up their `:` and `=`.
2022
>
21-
> - `==` stresses that this name will always have the given value, to express [aliases](./aliases.md) and side-effect-free 'constexpr' functions (e.g., `#!cpp square: (i: int) == i * i;`).
23+
> - `==` stresses that this name will always have the given value, to express [aliases](aliases.md) and side-effect-free 'constexpr' [function aliases](aliases.md/#function-aliases).
2224
2325

2426
## <a id="template-parameters"></a> Template parameters
@@ -27,13 +29,35 @@ A template parameter list is enclosed by `<` `>` angle brackets, and the paramet
2729

2830
For example:
2931

30-
``` cpp title="Declaring template parameters" hl_lines="1-3"
32+
``` cpp title="Declaring template parameters" hl_lines="1-3 8-9"
3133
array: <T: type, size: i32> type
3234
// parameter T is a type
3335
// parameter size is a 32-bit int
3436
= {
3537
// ...
3638
}
39+
40+
tuple: <Ts...: type> type
41+
// parameter Ts is variadic list of zero or more types
42+
= {
43+
// ...
44+
}
45+
```
46+
47+
48+
## <a id="requires"></a> `#!cpp requires` constraints
49+
50+
A `#!cpp requires` ***condition*** constraint appears at the end of the ***kind*** of a templated declaration. If the condition evaluates to `#!cpp false`, that specialization of the template is ignored as if not declared.
51+
52+
For example:
53+
54+
``` cpp title="A requires constraint on a variadic function" hl_lines="3"
55+
print: <Args...: type>
56+
(inout out: std::ostream, args...: Args)
57+
requires sizeof...(Args) >= 1u
58+
= {
59+
(out << ... << args);
60+
}
3761
```
3862

3963

@@ -97,9 +121,3 @@ n: namespace
97121
```
98122

99123
> Note: `@enum` is a metafunction, which provides an easy way to opt into a group of defaults, constraints, and generated functions. For details, see [`@enum`](metafunctions.md#enum).
100-
101-
102-
## <a id="requires"></a> `requires` constraints
103-
104-
TODO
105-

docs/cpp2/namespaces.md

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,58 @@
33

44
## Overview
55

6-
TODO
6+
A namespace `N` can contain declarations that are then accessed by writing `N::` or [`using`](#using) the namespace or declaration. For example:
77

8-
For details, see [Design note: Namespaces](https://github.com/hsutter/cppfront/wiki/Design-note%3A-Namespaces).
8+
``` cpp title="Declaring some things in a namespace" hl_lines="2 8"
9+
// A namespace to put all the names provided by a widget library
10+
widgetlib: namespace = {
11+
widget: type = { /*...*/ }
12+
// ... more things ...
13+
}
914

15+
main: () = {
16+
w: widgetlib::widget = /*...*/;
17+
}
18+
```
19+
20+
21+
## <a id="using"></a> `using`
22+
23+
A `#!cpp using` statement brings names declared in another namespace into the current scope as if they had been declared in the current scope. It has two forms:
24+
25+
- `#!cpp using a_namespace::a_name;` brings the single name `a_name` into scope.
26+
27+
- `#!cpp using namespace a_namespace;` brings all the namespace's names into scope.
28+
29+
For example:
30+
31+
``` cpp title="using statements" hl_lines="13 14 20 21"
32+
// A namespace to put all the names provided by a widget library
33+
widgetlib: namespace = {
34+
widget: type = { /*...*/ }
35+
// ... more things ...
36+
}
37+
38+
main: () = {
39+
// Explicit name qualification
40+
w: widgetlib::widget = /*...*/;
41+
42+
{
43+
// Using the name, no qualification needed
44+
using widgetlib::widget;
45+
w2: widget = /*...*/;
46+
// ...
47+
}
48+
49+
{
50+
// Using the whole namespace, no qualification needed
51+
using namespace widgetlib;
52+
w3: widget = /*...*/;
53+
// ...
54+
}
55+
56+
// ...
57+
}
58+
```
1059

11-
## `using`
1260

13-
TODO

0 commit comments

Comments
 (0)