Skip to content

Commit 6facf81

Browse files
committed
Embiggen text font, add move and out arguments
And code block cleanup: - highlight key lines in all code blocks - remove redundant "Example:" in code block titles - add a chained comparisons example
1 parent 9257d97 commit 6facf81

File tree

9 files changed

+83
-51
lines changed

9 files changed

+83
-51
lines changed

docs/cpp2/common.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ As always, `main` is the entry point of the program. For example:
1313
- Using `args` performs zero heap allocations. Every `string_view` is directly bound to the string storage provided by host environment.
1414
- `args.argc` and `args.argv` additionally provide access to the raw C/C++ `main` parameters.
1515

16-
``` cpp title="Examples: main with (args)"
16+
``` cpp title="main with (args)" hl_lines="5 9"
1717
// Print out command line arguments, then invoke
1818
// a Qt event loop for a non-UI Qt application
1919
main: (args) -> int
@@ -40,7 +40,7 @@ main: (args) -> int
4040

4141
The usual `// line comments` and `/* stream comments */` are supported. For example:
4242

43-
``` cpp title="Example: Comments"
43+
``` cpp title="Writing comments"
4444
// A line comment: After //, the entire
4545
// rest of the line is part of the comment
4646

@@ -98,7 +98,7 @@ Cpp2 supports the same fundamental types as today's Cpp1, but additionally provi
9898

9999
Types can be qualified with `const` and `*`. Types are written left-to-right, so a qualifier always applies to what immediately follows it. For example, to declare a `const` pointer to a non-`const` pointer to a `const i32` object, write:
100100

101-
``` cpp title="Example: Type qualifiers"
101+
``` cpp title="Using type qualifiers"
102102
// A const pointer to a non-const pointer to a const i32 object
103103
p: const * * const i32;
104104
```
@@ -123,7 +123,7 @@ Operators have the same precedence and associativity as in Cpp1, but some unary
123123

124124
The operators `!`, `+`, and `-` are prefix, as in Cpp1. For example:
125125

126-
``` cpp title="Example: Prefix operators"
126+
``` cpp title="Using prefix operators"
127127
if !vec.empty() {
128128
vec.emplace_back( -123.45 );
129129
}
@@ -137,7 +137,7 @@ if !vec.empty() {
137137

138138
The operators `.`, `*`, `&`, `~`, `++`, `--`, `()`, `[]`, and `$` are postfix. For example:
139139

140-
``` cpp title="Example: Postfix operators"
140+
``` cpp title="Using postfix operators"
141141
// Cpp1 examples, from cppfront's own source code:
142142
// address = &(*tokens)[pos + num];
143143
// is_void = *(*u)->identifier == "void";

docs/cpp2/declarations.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ All Cpp2 declarations are written as **"_name_ `:` _kind_ `=` _statement_"**.
1515

1616
## Examples
1717

18-
``` cpp title="Example: Consistent declarations — name : kind = statement"
18+
``` cpp title="Consistent declarations — name : kind = statement" hl_lines="2 5 10 17 21 25 34 40"
1919
// n is a namespace defined as the following scope
2020
n: namespace
2121
= {

docs/cpp2/expressions.md

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
`_` is pronounced **"don't care"** and allowed as a wildcard in most contexts. For example:
77

8-
``` cpp title="Example: _ wildcard"
8+
``` cpp title="Using the _ wildcard" hl_lines="2 5 11"
99
// We don't care about the guard variable's name
1010
_ : std::lock_guard = mut;
1111

@@ -22,7 +22,7 @@ return inspect v -> std::string {
2222

2323
Cpp2 treats all function outputs (return values, and results produced via `inout` and `out` parameters) as important, and does not let them be silently discarded by default. To explicitly discard such a value, assign it to `_`. For example:
2424

25-
``` cpp title="Example: Using _ for explicit discard"
25+
``` cpp title="Using _ for explicit discard" hl_lines="1 8"
2626
_ = vec.emplace_back(1,2,3);
2727
// "_ =" is required to explicitly discard emplace_back's
2828
// return value (which is non-void since C++17)
@@ -88,7 +88,7 @@ Here are some `is` queries with their Cpp1 equivalents. In this table, uppercase
8888

8989
An `x as T` expression allows safe type casts. `x` must be an object or expression, and `T` must be a type. It supports both static and dynamic typing, including customization with support for the standard dynamically typed libraries `std::variant`, `std::optional`, and `std::any` provided in the box. For example:
9090

91-
``` cpp title="Example: Using as"
91+
``` cpp title="Using as" hl_lines="4 6 14"
9292
main: () = {
9393
a: std::any = 0; // a's type is now int, value 0
9494
test(a); // prints "zero"
@@ -130,19 +130,21 @@ An `inspect expr -> Type` expression allows pattern matching using `is`.
130130

131131
For example:
132132

133-
``` cpp title="Example: Using inspect"
133+
``` cpp title="Using inspect" hl_lines="6-13"
134134
// A generic function that takes an argument 'x' of any type
135135
// and inspects various things about `x`
136136
test: (x) = {
137137
forty_two := 42;
138-
std::cout << inspect x -> std::string {
139-
is 0 = "zero"; // == 0
140-
is (forty_two) = "the answer"; // == 42
141-
is int = "integer"; // is type int (and not 0 or 42)
142-
is std::string = x as std::string; // is type std::string
143-
is std::vector = "a std::vector"; // is a vector</*of-some-type*/>
144-
is _ = "(no match)"; // is something else
145-
} << "\n";
138+
std::cout
139+
<< inspect x -> std::string {
140+
is 0 = "zero"; // == 0
141+
is (forty_two) = "the answer"; // == 42
142+
is int = "integer"; // is type int (and not 0 or 42)
143+
is std::string = x as std::string; // is type std::string
144+
is std::vector = "a std::vector"; // is a vector</*of-some-type*/>
145+
is _ = "(no match)"; // is something else
146+
}
147+
<< "\n";
146148
}
147149

148150
// Sample call site

docs/cpp2/functions.md

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,31 +7,48 @@ TODO
77

88
## Calling functions: `f(x)` syntax, and `x.f()` UFCS syntax
99

10-
A function call like `f(x)` is a normal non-member function call. It will call non-member functions only.
10+
A function call like `f(x)` is a normal function call that will call non-member functions only, as usual in C++.
1111

1212
A function call like `x.f()` is a unified function call syntax (aka UFCS) call. It will call a member function if one is available, and otherwise will call `f(x)`. Having UFCS is important for generic code that may want to call a member or a non-member function, whichever is available. It's also important to enable fluid programming styles and natural IDE autocompletion support.
1313

14+
An operator notation call like `a + b` will call an overloaded operator function if one is available, as usual in C++.
15+
1416
For example:
1517

16-
``` cpp title="Example: Function calls"
18+
``` cpp title="Function calls" hl_lines="3 7 11 16 19 20"
19+
// Generic function to log something
20+
// This calls operator<< using operator notation
21+
log: (x) = clog << x;
22+
1723
f: ( v : std::vector<widget> ) = {
18-
// This calls std::vector::size()
19-
std::cout << v.size();
24+
// This calls log() with the result of std::vector::size()
25+
log( v.size() );
2026

21-
// This calls std::ssize(v), because v
22-
// doesn't have a .ssize member function
23-
std::cout << v.ssize();
27+
// This calls log() with the result of std::ssize(v), because
28+
// v doesn't have a .ssize member function
29+
log( v.ssize() );
2430
}
2531

2632
// Generic function to print "hello, ___!" for any printable type
2733
hello: (name) = {
28-
// Using the C standard library is arguably nicer with UFCS
2934
myfile := fopen("xyzzy.txt", "w");
30-
myfile.fprintf( "Hello, (name)%!\n" );
35+
// Direct calls to C nonmember functions, using UFCS and safe
36+
// string interpolation (instead of type-unsafe format strings)
37+
myfile.fprintf( "Hello, (name)$!\n" );
3138
myfile.fclose();
39+
// The C and C++ standard libraries are not only fully available,
40+
// but safer (and arguably nicer) when used from Cpp2 syntax code
3241
}
3342
```
3443

44+
To explicitly treat an object name passed as an argument as `move` or `out`, write that keyword before the variable name.
45+
46+
- Explicit `move` is rarely needed. Every definite last use of a local variable will apply `move` by default. Writing `move` from an object before its definite last use means that later uses may see a moved-from state.
47+
48+
- Explicit `out` is needed only when initializing a local variable separately from its declaration using a call to a function with an `out` parameter. For details, see [Guaranteed initialization](../cpp2/objects.md#Init).
49+
50+
For example:
51+
3552

3653
## Parameters
3754

@@ -62,7 +79,7 @@ A function's outputs are its return values, and the "out" state of any `out` and
6279

6380
Function outputs cannot be silently discarded. To explicitly discard a function output, assign it to `_`. For example:
6481

65-
``` cpp title="Example: No silent discard"
82+
``` cpp title="No silent discard" hl_lines="10 11 22 27"
6683
f: () -> void = { }
6784
g: () -> int = { return 10; }
6885
h: (inout x: int) -> void = { x = 20; }
@@ -84,7 +101,7 @@ main: ()
84101
{
85102
x := 0;
86103
h( x ); // ok, x is referred to again...
87-
_ = x; // ... here, its value explicitly discarded
104+
_ = x; // ... here where its value explicitly discarded
88105
}
89106

90107
{
@@ -114,7 +131,7 @@ TODO
114131

115132
Loops can be named using the usual **name `:`** name introduction syntax, and `break` and `continue` can refer to those names. For example:
116133

117-
``` cpp title="Example: Writing a simple type"
134+
``` cpp title="Using named break and continue" hl_lines="6 10"
118135
outer: while i<M next i++ { // loop named "outer"
119136
// ...
120137
inner: while j<N next j++ { // loop named "inner"

docs/cpp2/metafunctions.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ The most important thing about metafunctions is that they are not hardwired lang
1515

1616
Metafunctions provide an easy way for a type author to opt into a group of defaults, constraints, and generated functions: Just write `@name` afer the `:` of a declaration, where `name` is the name of the metafunctions. This lets the type author declare (and the human reader see) the intent up front: "This isn't just any `type`, this is a `@value type`" which automatically gives the type default/copy/move construction and assignment, `<=>` with `std::strong_ordering` comparisons, and guarantees that it has a public destructor and no protected or virtual functions:
1717

18-
``` cpp title="Example: Using the value metafunction when writing a type"
18+
``` cpp title="Using the value metafunction when writing a type" hl_lines="1"
1919
point2d: @value type = {
2020
x: i32 = 0;
2121
y: i32 = 0;
@@ -69,7 +69,7 @@ TODO
6969

7070
Cpp2 has no `enum` feature hardwired into the language. Instead you apply the `@enum` metafunction when writing an ordinary `type`:
7171

72-
``` cpp title="Example: Using @enum"
72+
``` cpp title="Using the @enum metafunction when writing a type" hl_lines="14"
7373
// skat_game is declaratively a safe enumeration type: it has
7474
// default/copy/move construction/assignment and <=> with
7575
// std::strong_ordering, a minimal-size signed underlying type
@@ -99,7 +99,7 @@ Unlike C `enum`, this `@enum` is scoped and strongly typed (does not implicitly
9999

100100
Unlike C++11 `enum class`, it's "just a `type`" which means it can naturally also have member functions and other things that a type can have:
101101

102-
``` cpp title="Example: An @enum type with a member function"
102+
``` cpp title="An @enum type with a member function" hl_lines="1"
103103
janus: @enum type = {
104104
past;
105105
future;
@@ -113,7 +113,7 @@ janus: @enum type = {
113113

114114
There's also a `flag_enum` variation with power-of-two semantics and an unsigned underlying type:
115115

116-
``` cpp title="Example: Using @flag_enum"
116+
``` cpp title="Using the @flag_enum metafunction when writing a type" hl_lines="11"
117117
// file_attributes is declaratively a safe flag enum type:
118118
// same as enum, but with a minimal-size unsigned underlying
119119
// type by default, and values that automatically start at 1
@@ -137,7 +137,7 @@ file_attributes: @flag_enum<u8> type = {
137137

138138
`@union` declaratively opts into writing a safe discriminated union/variant dynamic type. For example:
139139

140-
``` cpp title="Example: Using @union"
140+
``` cpp title="Using the @union metafunction when writing a type" hl_lines="9"
141141
// name_or_number is declaratively a safe union/variant type:
142142
// it has a discriminant that enforces only one alternative
143143
// can be active at a time, members always have a name, and
@@ -173,7 +173,7 @@ Each `@union` type has its own type-safe name, has clear and unambiguous named m
173173

174174
Because a `@union type` is still a `type`, it can naturally have other things normal types can have, such as template parameter lists and member functions:
175175

176-
``` cpp title="Example: A templated custom safe union type"
176+
``` cpp title="A templated custom safe union type" hl_lines="1"
177177
name_or_other: @union <T:type> type
178178
= {
179179
name : std::string;

docs/cpp2/objects.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Its declaration is written using the same **name `:` kind `=` value** [declarati
1313

1414
For example:
1515

16-
``` cpp title="Example: Declaring some objects"
16+
``` cpp title="Declaring some objects"
1717
// numbers is an object of type std::vector<point2d>,
1818
// defined as having the initial contents 1, 2, 3
1919
numbers: std::vector<int> = (1, 2, 3);
@@ -26,13 +26,13 @@ count := -1; // same, deducing the object's type by just omitting it
2626
```
2727

2828

29-
## Guaranteed initialization
29+
## <a id="Init"></a> Guaranteed initialization
3030

3131
Every object must be initialized using `=` before it is used.
3232

3333
An object in any scope can be initialized at its declaration. For example:
3434

35-
``` cpp title="Example: Initializing objects when they are declared" hl_lines="4 10"
35+
``` cpp title="Initializing objects when they are declared" hl_lines="4 10"
3636
shape: type = {
3737
// An object at type scope (data member)
3838
// initialized with its type's default value
@@ -61,7 +61,7 @@ Additionally, at function local scope an object `obj` can be initialized separat
6161

6262
For example:
6363

64-
``` cpp title="Example: Initializing local objects after they are declared"
64+
``` cpp title="Initializing local objects after they are declared" hl_lines="5 14 17 21"
6565
f: () = {
6666
buf: std::array<std::byte, 1024>; // uninitialized
6767
// ... calculate some things ...
@@ -108,7 +108,7 @@ The default is `unique.new` if you don't specify an arena object.
108108
For example (see [types](types.md) for more details about writing types):
109109

110110

111-
``` cpp title="Example: Heap allocation"
111+
``` cpp title="Heap allocation" hl_lines="3-6 10-11"
112112
f: () -> std::shared_ptr<widget>
113113
= {
114114
// Dynamically allocate an object owned by a std::unique_ptr

docs/cpp2/types.md

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ A user-defined `type` is written using the same **name `:` kind `=` value** [dec
77

88
In a `type`, data members are private by default, and functions and nested types are public by default. To explicitly declare a type scope declaration `public`, `protected`, or `private`, write that keyword at the beginning of the declaration.
99

10-
``` cpp title="Example: Writing a simple type"
10+
``` cpp title="Writing a simple type" hl_lines="1"
1111
mytype: type =
1212
{
1313
// data members are private by default
@@ -40,7 +40,7 @@ The name `this` may only be used for the first parameter of a type-scope functio
4040

4141
For example, here is how to write read-only member function named `print` that takes a read-only string value and prints this object's data value and the string message:
4242

43-
``` cpp title="Example: this"
43+
``` cpp title="The this parameter" hl_lines="4 6"
4444
mytype: type = {
4545
data: i32; // some data member (private by default)
4646

@@ -73,11 +73,11 @@ A `this` parameter can additionally be declared as one of the following:
7373

7474
- **`final`**: Writing `myfunc: (final this /*...*/)` defines a final override of an existing base class virtual function.
7575

76-
A pure virtual function is a function with a `virtual this` parameter and no body.
76+
A pure virtual function is a function with a `virtual this` or `override this` parameter and no body.
7777

7878
For example:
7979

80-
``` cpp title="Example: Virtual functions"
80+
``` cpp title="Virtual functions" hl_lines="3 4 14 15"
8181
abstract_base: type
8282
= {
8383
// A pure virtual function: virtual + no body
@@ -187,7 +187,7 @@ All copy/move/comparison `operator=` functions are memberwise by default in Cpp2
187187

188188
For example:
189189

190-
``` cpp title="Memberwise operator= semantics
190+
``` cpp title="Memberwise operator= semantics" hl_lines="9-11 20-22"
191191
mytype: type
192192
= {
193193
// data members (private by default)
@@ -242,5 +242,12 @@ Most of Cpp2's `operator<=>` has already been merged into ISO C++, except for al
242242

243243
- **Invalid chains: Everything else.** Nonsense chains like `a >= b < c` and `a != b != c` are compile time errors. They are "nonsense" because they are non-transitive; these chains do not imply any relationship between `a` and `c`.
244244

245+
``` cpp title="Chained comparisons" hl_lines="2"
246+
// If requested is in the range of values [lo, hi)
247+
if lo <= requested < hi {
248+
// ... do something ...
249+
}
250+
```
251+
245252
For details, see [P0515 "Consistent comparison" section 3.3](https://wg21.link/p0515) and [P0893 "Chaining comparisons"](https://wg21.link/p0893).
246253

docs/stylesheets/extra.css

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
/*
2+
the default font sizes look small and encourage zooming,
3+
which loses the navigation side panels
4+
*/
5+
p { font-size: 16px; }
6+
td { font-size: 16px; }
17

28
/*
39
todo: try to make the nav pane section labels larger
@@ -6,4 +12,4 @@
612
to section starts are easier to see
713
*/
814
.md-nav__item { font-size: 20pt; }
9-
.md-nav__link { font-size: medium; }
15+
.md-nav__link { font-size: medium; }

mkdocs.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,10 @@ nav:
5858
- 'Common expressions': cpp2/expressions.md
5959
- 'Declaration syntax': cpp2/declarations.md
6060
- 'Objects, initialization, and memory': cpp2/objects.md
61-
- 'Functions': cpp2/functions.md
62-
- 'Contracts': cpp2/contracts.md
63-
- 'Types': cpp2/types.md
64-
- 'Metafunctions & reflection API': cpp2/metafunctions.md
61+
- 'Functions, branches, and loops': cpp2/functions.md
62+
- 'Contracts and assertions': cpp2/contracts.md
63+
- 'Types and inheritance': cpp2/types.md
64+
- 'Metafunctions and reflection': cpp2/metafunctions.md
6565
- 'Namespaces': cpp2/namespaces.md
6666
- 'Aliases': cpp2/aliases.md
6767
- 'Modules': cpp2/modules.md

0 commit comments

Comments
 (0)