- tmp/tmpq2jbfqnl/{from.md → to.md} +135 -73
tmp/tmpq2jbfqnl/{from.md → to.md}
RENAMED
|
@@ -10,23 +10,31 @@ template-parameter:
|
|
| 10 |
|
| 11 |
``` bnf
|
| 12 |
type-parameter:
|
| 13 |
type-parameter-key '...'ₒₚₜ identifierₒₚₜ
|
| 14 |
type-parameter-key identifierₒₚₜ '=' type-id
|
| 15 |
-
|
| 16 |
-
|
|
|
|
|
|
|
| 17 |
```
|
| 18 |
|
| 19 |
``` bnf
|
| 20 |
type-parameter-key:
|
| 21 |
-
|
| 22 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
```
|
| 24 |
|
| 25 |
[*Note 1*: The `>` token following the *template-parameter-list* of a
|
| 26 |
*type-parameter* may be the product of replacing a `>{>}` token by two
|
| 27 |
-
consecutive `>` tokens
|
| 28 |
|
| 29 |
There is no semantic difference between `class` and `typename` in a
|
| 30 |
*type-parameter-key*. `typename` followed by an *unqualified-id* names a
|
| 31 |
template type parameter. `typename` followed by a *qualified-id* denotes
|
| 32 |
the type in a non-type [^1] *parameter-declaration*. A
|
|
@@ -74,66 +82,112 @@ class Map {
|
|
| 74 |
};
|
| 75 |
```
|
| 76 |
|
| 77 |
— *end note*]
|
| 78 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 79 |
A non-type *template-parameter* shall have one of the following
|
| 80 |
-
(
|
| 81 |
|
| 82 |
-
-
|
| 83 |
-
-
|
| 84 |
-
-
|
| 85 |
-
- pointer to member,
|
| 86 |
-
- `std::nullptr_t`, or
|
| 87 |
-
- a type that contains a placeholder type ([[dcl.spec.auto]]).
|
| 88 |
-
|
| 89 |
-
[*Note 3*: Other types are disallowed either explicitly below or
|
| 90 |
-
implicitly by the rules governing the form of *template-argument*s (
|
| 91 |
-
[[temp.arg]]). — *end note*]
|
| 92 |
|
| 93 |
The top-level *cv-qualifier*s on the *template-parameter* are ignored
|
| 94 |
when determining its type.
|
| 95 |
|
| 96 |
-
A
|
| 97 |
-
be assigned to or in any other way have its value changed. A non-type
|
| 98 |
-
non-reference *template-parameter* cannot have its address taken. When a
|
| 99 |
-
non-type non-reference *template-parameter* is used as an initializer
|
| 100 |
-
for a reference, a temporary is always used.
|
| 101 |
|
| 102 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 103 |
|
| 104 |
``` cpp
|
| 105 |
-
|
|
|
|
|
|
|
| 106 |
i++; // error: change of template-parameter value
|
| 107 |
|
| 108 |
&x; // OK
|
| 109 |
&i; // error: address of non-reference template-parameter
|
| 110 |
-
|
| 111 |
int& ri = i; // error: non-const reference bound to temporary
|
| 112 |
const int& cri = i; // OK: const reference bound to temporary
|
|
|
|
| 113 |
}
|
| 114 |
```
|
| 115 |
|
| 116 |
— *end example*]
|
| 117 |
|
| 118 |
-
|
| 119 |
-
floating-point, class, or void type.
|
| 120 |
|
| 121 |
-
|
|
|
|
|
|
|
|
|
|
| 122 |
|
| 123 |
``` cpp
|
| 124 |
-
template<
|
| 125 |
-
template<
|
| 126 |
-
template<double& rd> class Z; // OK
|
| 127 |
```
|
| 128 |
|
| 129 |
— *end example*]
|
| 130 |
|
|
|
|
|
|
|
| 131 |
A non-type *template-parameter* of type “array of `T`” or of function
|
| 132 |
type `T` is adjusted to be of type “pointer to `T`”.
|
| 133 |
|
| 134 |
-
[*Example
|
| 135 |
|
| 136 |
``` cpp
|
| 137 |
template<int* a> struct R { ... };
|
| 138 |
template<int b[5]> struct S { ... };
|
| 139 |
int p;
|
|
@@ -144,30 +198,35 @@ R<v> y; // OK due to implicit argument conversion
|
|
| 144 |
S<v> z; // OK due to both adjustment and conversion
|
| 145 |
```
|
| 146 |
|
| 147 |
— *end example*]
|
| 148 |
|
| 149 |
-
A
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 150 |
specified after `=` in a *template-parameter*. A default
|
| 151 |
*template-argument* may be specified for any kind of
|
| 152 |
*template-parameter* (type, non-type, template) that is not a template
|
| 153 |
-
parameter pack
|
| 154 |
-
|
| 155 |
-
|
| 156 |
-
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
|
| 160 |
-
|
| 161 |
-
|
| 162 |
|
| 163 |
The set of default *template-argument*s available for use is obtained by
|
| 164 |
merging the default arguments from all prior declarations of the
|
| 165 |
-
template in the same way default function arguments are
|
| 166 |
-
[[dcl.fct.default]]
|
| 167 |
|
| 168 |
-
[*Example
|
| 169 |
|
| 170 |
``` cpp
|
| 171 |
template<class T1, class T2 = int> class A;
|
| 172 |
template<class T1 = int, class T2> class A;
|
| 173 |
```
|
|
@@ -186,17 +245,17 @@ alias template has a default *template-argument*, each subsequent
|
|
| 186 |
supplied or be a template parameter pack. If a *template-parameter* of a
|
| 187 |
primary class template, primary variable template, or alias template is
|
| 188 |
a template parameter pack, it shall be the last *template-parameter*. A
|
| 189 |
template parameter pack of a function template shall not be followed by
|
| 190 |
another template parameter unless that template parameter can be deduced
|
| 191 |
-
from the parameter-type-list
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
|
| 195 |
deduction guide template.
|
| 196 |
|
| 197 |
-
[*Example
|
| 198 |
|
| 199 |
``` cpp
|
| 200 |
template<class T1 = int, class T2> class B; // error
|
| 201 |
|
| 202 |
// U can be neither deduced from the parameter-type-list nor specified
|
|
@@ -207,11 +266,11 @@ template<class... T, class U> void g() { } // error
|
|
| 207 |
— *end example*]
|
| 208 |
|
| 209 |
A *template-parameter* shall not be given default arguments by two
|
| 210 |
different declarations in the same scope.
|
| 211 |
|
| 212 |
-
[*Example
|
| 213 |
|
| 214 |
``` cpp
|
| 215 |
template<class T = int> class X;
|
| 216 |
template<class T = int> class X { ... }; // error
|
| 217 |
```
|
|
@@ -220,11 +279,11 @@ template<class T = int> class X { ... }; // error
|
|
| 220 |
|
| 221 |
When parsing a default *template-argument* for a non-type
|
| 222 |
*template-parameter*, the first non-nested `>` is taken as the end of
|
| 223 |
the *template-parameter-list* rather than a greater-than operator.
|
| 224 |
|
| 225 |
-
[*Example
|
| 226 |
|
| 227 |
``` cpp
|
| 228 |
template<int i = 3 > 4 > // syntax error
|
| 229 |
class X { ... };
|
| 230 |
|
|
@@ -237,52 +296,55 @@ class Y { ... };
|
|
| 237 |
A *template-parameter* of a template *template-parameter* is permitted
|
| 238 |
to have a default *template-argument*. When such default arguments are
|
| 239 |
specified, they apply to the template *template-parameter* in the scope
|
| 240 |
of the template *template-parameter*.
|
| 241 |
|
| 242 |
-
[*Example
|
| 243 |
|
| 244 |
``` cpp
|
| 245 |
-
template <class T = float> struct B {};
|
| 246 |
template <template <class TT = float> class T> struct A {
|
| 247 |
inline void f();
|
| 248 |
inline void g();
|
| 249 |
};
|
| 250 |
template <template <class TT> class T> void A<T>::f() {
|
| 251 |
-
T<> t; // error
|
| 252 |
}
|
| 253 |
template <template <class TT = char> class T> void A<T>::g() {
|
| 254 |
-
|
| 255 |
}
|
| 256 |
```
|
| 257 |
|
| 258 |
— *end example*]
|
| 259 |
|
| 260 |
If a *template-parameter* is a *type-parameter* with an ellipsis prior
|
| 261 |
to its optional *identifier* or is a *parameter-declaration* that
|
| 262 |
-
declares a
|
| 263 |
-
|
| 264 |
-
|
| 265 |
-
|
| 266 |
-
parameter
|
| 267 |
-
|
| 268 |
-
|
| 269 |
-
expansion
|
|
|
|
| 270 |
*template-parameter-list*.
|
| 271 |
|
| 272 |
-
[*Example
|
| 273 |
|
| 274 |
``` cpp
|
| 275 |
-
template <class... Types>
|
| 276 |
-
|
| 277 |
-
|
| 278 |
-
|
| 279 |
-
|
|
|
|
|
|
|
|
|
|
| 280 |
template <T... Values> struct apply { }; // Values is a non-type template parameter pack
|
| 281 |
-
|
| 282 |
-
|
| 283 |
-
template<class... T, T... Values>
|
| 284 |
-
|
| 285 |
```
|
| 286 |
|
| 287 |
— *end example*]
|
| 288 |
|
|
|
|
| 10 |
|
| 11 |
``` bnf
|
| 12 |
type-parameter:
|
| 13 |
type-parameter-key '...'ₒₚₜ identifierₒₚₜ
|
| 14 |
type-parameter-key identifierₒₚₜ '=' type-id
|
| 15 |
+
type-constraint '...'ₒₚₜ identifierₒₚₜ
|
| 16 |
+
type-constraint identifierₒₚₜ '=' type-id
|
| 17 |
+
template-head type-parameter-key '...'ₒₚₜ identifierₒₚₜ
|
| 18 |
+
template-head type-parameter-key identifierₒₚₜ '=' id-expression
|
| 19 |
```
|
| 20 |
|
| 21 |
``` bnf
|
| 22 |
type-parameter-key:
|
| 23 |
+
class
|
| 24 |
+
typename
|
| 25 |
+
```
|
| 26 |
+
|
| 27 |
+
``` bnf
|
| 28 |
+
type-constraint:
|
| 29 |
+
nested-name-specifierₒₚₜ concept-name
|
| 30 |
+
nested-name-specifierₒₚₜ concept-name '<' template-argument-listₒₚₜ '>'
|
| 31 |
```
|
| 32 |
|
| 33 |
[*Note 1*: The `>` token following the *template-parameter-list* of a
|
| 34 |
*type-parameter* may be the product of replacing a `>{>}` token by two
|
| 35 |
+
consecutive `>` tokens [[temp.names]]. — *end note*]
|
| 36 |
|
| 37 |
There is no semantic difference between `class` and `typename` in a
|
| 38 |
*type-parameter-key*. `typename` followed by an *unqualified-id* names a
|
| 39 |
template type parameter. `typename` followed by a *qualified-id* denotes
|
| 40 |
the type in a non-type [^1] *parameter-declaration*. A
|
|
|
|
| 82 |
};
|
| 83 |
```
|
| 84 |
|
| 85 |
— *end note*]
|
| 86 |
|
| 87 |
+
A *type-constraint* `Q` that designates a concept `C` can be used to
|
| 88 |
+
constrain a contextually-determined type or template type parameter pack
|
| 89 |
+
`T` with a *constraint-expression* `E` defined as follows. If `Q` is of
|
| 90 |
+
the form `C<A₁, ⋯, Aₙ>`, then let `E'` be `C<T, A₁, ⋯, Aₙ>`. Otherwise,
|
| 91 |
+
let `E'` be `C<T>`. If `T` is not a pack, then `E` is `E'`, otherwise
|
| 92 |
+
`E` is `(E' && ...)`. This *constraint-expression* `E` is called the
|
| 93 |
+
*immediately-declared constraint* of `Q` for `T`. The concept designated
|
| 94 |
+
by a *type-constraint* shall be a type concept [[temp.concept]].
|
| 95 |
+
|
| 96 |
+
A *type-parameter* that starts with a *type-constraint* introduces the
|
| 97 |
+
immediately-declared constraint of the *type-constraint* for the
|
| 98 |
+
parameter.
|
| 99 |
+
|
| 100 |
+
[*Example 2*:
|
| 101 |
+
|
| 102 |
+
``` cpp
|
| 103 |
+
template<typename T> concept C1 = true;
|
| 104 |
+
template<typename... Ts> concept C2 = true;
|
| 105 |
+
template<typename T, typename U> concept C3 = true;
|
| 106 |
+
|
| 107 |
+
template<C1 T> struct s1; // associates C1<T>
|
| 108 |
+
template<C1... T> struct s2; // associates (C1<T> && ...)
|
| 109 |
+
template<C2... T> struct s3; // associates (C2<T> && ...)
|
| 110 |
+
template<C3<int> T> struct s4; // associates C3<T, int>
|
| 111 |
+
template<C3<int>... T> struct s5; // associates (C3<T, int> && ...)
|
| 112 |
+
```
|
| 113 |
+
|
| 114 |
+
— *end example*]
|
| 115 |
+
|
| 116 |
A non-type *template-parameter* shall have one of the following
|
| 117 |
+
(possibly cv-qualified) types:
|
| 118 |
|
| 119 |
+
- a structural type (see below),
|
| 120 |
+
- a type that contains a placeholder type [[dcl.spec.auto]], or
|
| 121 |
+
- a placeholder for a deduced class type [[dcl.type.class.deduct]].
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 122 |
|
| 123 |
The top-level *cv-qualifier*s on the *template-parameter* are ignored
|
| 124 |
when determining its type.
|
| 125 |
|
| 126 |
+
A *structural type* is one of the following:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 127 |
|
| 128 |
+
- a scalar type, or
|
| 129 |
+
- an lvalue reference type, or
|
| 130 |
+
- a literal class type with the following properties:
|
| 131 |
+
- all base classes and non-static data members are public and
|
| 132 |
+
non-mutable and
|
| 133 |
+
- the types of all bases classes and non-static data members are
|
| 134 |
+
structural types or (possibly multi-dimensional) array thereof.
|
| 135 |
+
|
| 136 |
+
An *id-expression* naming a non-type *template-parameter* of class type
|
| 137 |
+
`T` denotes a static storage duration object of type `const T`, known as
|
| 138 |
+
a *template parameter object*, whose value is that of the corresponding
|
| 139 |
+
template argument after it has been converted to the type of the
|
| 140 |
+
*template-parameter*. All such template parameters in the program of the
|
| 141 |
+
same type with the same value denote the same template parameter object.
|
| 142 |
+
A template parameter object shall have constant destruction
|
| 143 |
+
[[expr.const]].
|
| 144 |
+
|
| 145 |
+
[*Note 3*: If an *id-expression* names a non-type non-reference
|
| 146 |
+
*template-parameter*, then it is a prvalue if it has non-class type.
|
| 147 |
+
Otherwise, if it is of class type `T`, it is an lvalue and has type
|
| 148 |
+
`const T` [[expr.prim.id.unqual]]. — *end note*]
|
| 149 |
+
|
| 150 |
+
[*Example 3*:
|
| 151 |
|
| 152 |
``` cpp
|
| 153 |
+
using X = int;
|
| 154 |
+
struct A {};
|
| 155 |
+
template<const X& x, int i, A a> void f() {
|
| 156 |
i++; // error: change of template-parameter value
|
| 157 |
|
| 158 |
&x; // OK
|
| 159 |
&i; // error: address of non-reference template-parameter
|
| 160 |
+
&a; // OK
|
| 161 |
int& ri = i; // error: non-const reference bound to temporary
|
| 162 |
const int& cri = i; // OK: const reference bound to temporary
|
| 163 |
+
const A& ra = a; // OK: const reference bound to a template parameter object
|
| 164 |
}
|
| 165 |
```
|
| 166 |
|
| 167 |
— *end example*]
|
| 168 |
|
| 169 |
+
[*Note 4*:
|
|
|
|
| 170 |
|
| 171 |
+
A non-type *template-parameter* cannot be declared to have type cv
|
| 172 |
+
`void`.
|
| 173 |
+
|
| 174 |
+
[*Example 4*:
|
| 175 |
|
| 176 |
``` cpp
|
| 177 |
+
template<void v> class X; // error
|
| 178 |
+
template<void* pv> class Y; // OK
|
|
|
|
| 179 |
```
|
| 180 |
|
| 181 |
— *end example*]
|
| 182 |
|
| 183 |
+
— *end note*]
|
| 184 |
+
|
| 185 |
A non-type *template-parameter* of type “array of `T`” or of function
|
| 186 |
type `T` is adjusted to be of type “pointer to `T`”.
|
| 187 |
|
| 188 |
+
[*Example 5*:
|
| 189 |
|
| 190 |
``` cpp
|
| 191 |
template<int* a> struct R { ... };
|
| 192 |
template<int b[5]> struct S { ... };
|
| 193 |
int p;
|
|
|
|
| 198 |
S<v> z; // OK due to both adjustment and conversion
|
| 199 |
```
|
| 200 |
|
| 201 |
— *end example*]
|
| 202 |
|
| 203 |
+
A non-type template parameter declared with a type that contains a
|
| 204 |
+
placeholder type with a *type-constraint* introduces the
|
| 205 |
+
immediately-declared constraint of the *type-constraint* for the
|
| 206 |
+
invented type corresponding to the placeholder [[dcl.fct]].
|
| 207 |
+
|
| 208 |
+
A *default template-argument* is a *template-argument* [[temp.arg]]
|
| 209 |
specified after `=` in a *template-parameter*. A default
|
| 210 |
*template-argument* may be specified for any kind of
|
| 211 |
*template-parameter* (type, non-type, template) that is not a template
|
| 212 |
+
parameter pack [[temp.variadic]]. A default *template-argument* may be
|
| 213 |
+
specified in a template declaration. A default *template-argument* shall
|
| 214 |
+
not be specified in the *template-parameter-list*s of the definition of
|
| 215 |
+
a member of a class template that appears outside of the member’s class.
|
| 216 |
+
A default *template-argument* shall not be specified in a friend class
|
| 217 |
+
template declaration. If a friend function template declaration
|
| 218 |
+
specifies a default *template-argument*, that declaration shall be a
|
| 219 |
+
definition and shall be the only declaration of the function template in
|
| 220 |
+
the translation unit.
|
| 221 |
|
| 222 |
The set of default *template-argument*s available for use is obtained by
|
| 223 |
merging the default arguments from all prior declarations of the
|
| 224 |
+
template in the same way default function arguments are
|
| 225 |
+
[[dcl.fct.default]].
|
| 226 |
|
| 227 |
+
[*Example 6*:
|
| 228 |
|
| 229 |
``` cpp
|
| 230 |
template<class T1, class T2 = int> class A;
|
| 231 |
template<class T1 = int, class T2> class A;
|
| 232 |
```
|
|
|
|
| 245 |
supplied or be a template parameter pack. If a *template-parameter* of a
|
| 246 |
primary class template, primary variable template, or alias template is
|
| 247 |
a template parameter pack, it shall be the last *template-parameter*. A
|
| 248 |
template parameter pack of a function template shall not be followed by
|
| 249 |
another template parameter unless that template parameter can be deduced
|
| 250 |
+
from the parameter-type-list [[dcl.fct]] of the function template or has
|
| 251 |
+
a default argument [[temp.deduct]]. A template parameter of a deduction
|
| 252 |
+
guide template [[temp.deduct.guide]] that does not have a default
|
| 253 |
+
argument shall be deducible from the parameter-type-list of the
|
| 254 |
deduction guide template.
|
| 255 |
|
| 256 |
+
[*Example 7*:
|
| 257 |
|
| 258 |
``` cpp
|
| 259 |
template<class T1 = int, class T2> class B; // error
|
| 260 |
|
| 261 |
// U can be neither deduced from the parameter-type-list nor specified
|
|
|
|
| 266 |
— *end example*]
|
| 267 |
|
| 268 |
A *template-parameter* shall not be given default arguments by two
|
| 269 |
different declarations in the same scope.
|
| 270 |
|
| 271 |
+
[*Example 8*:
|
| 272 |
|
| 273 |
``` cpp
|
| 274 |
template<class T = int> class X;
|
| 275 |
template<class T = int> class X { ... }; // error
|
| 276 |
```
|
|
|
|
| 279 |
|
| 280 |
When parsing a default *template-argument* for a non-type
|
| 281 |
*template-parameter*, the first non-nested `>` is taken as the end of
|
| 282 |
the *template-parameter-list* rather than a greater-than operator.
|
| 283 |
|
| 284 |
+
[*Example 9*:
|
| 285 |
|
| 286 |
``` cpp
|
| 287 |
template<int i = 3 > 4 > // syntax error
|
| 288 |
class X { ... };
|
| 289 |
|
|
|
|
| 296 |
A *template-parameter* of a template *template-parameter* is permitted
|
| 297 |
to have a default *template-argument*. When such default arguments are
|
| 298 |
specified, they apply to the template *template-parameter* in the scope
|
| 299 |
of the template *template-parameter*.
|
| 300 |
|
| 301 |
+
[*Example 10*:
|
| 302 |
|
| 303 |
``` cpp
|
|
|
|
| 304 |
template <template <class TT = float> class T> struct A {
|
| 305 |
inline void f();
|
| 306 |
inline void g();
|
| 307 |
};
|
| 308 |
template <template <class TT> class T> void A<T>::f() {
|
| 309 |
+
T<> t; // error: TT has no default template argument
|
| 310 |
}
|
| 311 |
template <template <class TT = char> class T> void A<T>::g() {
|
| 312 |
+
T<> t; // OK, T<char>
|
| 313 |
}
|
| 314 |
```
|
| 315 |
|
| 316 |
— *end example*]
|
| 317 |
|
| 318 |
If a *template-parameter* is a *type-parameter* with an ellipsis prior
|
| 319 |
to its optional *identifier* or is a *parameter-declaration* that
|
| 320 |
+
declares a pack [[dcl.fct]], then the *template-parameter* is a template
|
| 321 |
+
parameter pack [[temp.variadic]]. A template parameter pack that is a
|
| 322 |
+
*parameter-declaration* whose type contains one or more unexpanded packs
|
| 323 |
+
is a pack expansion. Similarly, a template parameter pack that is a
|
| 324 |
+
*type-parameter* with a *template-parameter-list* containing one or more
|
| 325 |
+
unexpanded packs is a pack expansion. A type parameter pack with a
|
| 326 |
+
*type-constraint* that contains an unexpanded parameter pack is a pack
|
| 327 |
+
expansion. A template parameter pack that is a pack expansion shall not
|
| 328 |
+
expand a template parameter pack declared in the same
|
| 329 |
*template-parameter-list*.
|
| 330 |
|
| 331 |
+
[*Example 11*:
|
| 332 |
|
| 333 |
``` cpp
|
| 334 |
+
template <class... Types> // Types is a template type parameter pack
|
| 335 |
+
class Tuple; // but not a pack expansion
|
| 336 |
+
|
| 337 |
+
template <class T, int... Dims> // Dims is a non-type template parameter pack
|
| 338 |
+
struct multi_array; // but not a pack expansion
|
| 339 |
+
|
| 340 |
+
template <class... T>
|
| 341 |
+
struct value_holder {
|
| 342 |
template <T... Values> struct apply { }; // Values is a non-type template parameter pack
|
| 343 |
+
}; // and a pack expansion
|
| 344 |
+
|
| 345 |
+
template <class... T, T... Values> // error: Values expands template type parameter
|
| 346 |
+
struct static_array; // pack T within the same template parameter list
|
| 347 |
```
|
| 348 |
|
| 349 |
— *end example*]
|
| 350 |
|