This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.

### 3193. Mandates: and Expects: elements are not defined for types

Section: 16.3.2.4 [structure.specifications] Status: New Submitter: Daniel Krügler Opened: 2019-03-04 Last modified: 2020-06-11

Priority: 3

View other active issues in [structure.specifications].

View all other issues in [structure.specifications].

View all issues with New status.

Discussion:

The working paper uses the special elements Mandates:, Expects: as well as Requires: to types, albeit 16.3.2.4 [structure.specifications] defines them only for functions, for example 16.3.2.4 [structure.specifications] sub-bullet (3.4):

> Expects: the conditions (sometimes termed preconditions) that the function assumes to hold whenever it is called.

Examples for such usages on types are (from N4800):

- 23.2.3 [char.traits.typedefs] for types `int_type` and `state_type`

- 22.3.4 [pair.astuple] for `tuple_element<I, pair<T1, T2>>::type`

- 22.4.7 [tuple.helper] for `tuple_element<I, tuple<Types...>>::type`

- 22.4.11 [tuple.traits] for `uses_allocator<tuple<Types...>, Alloc>`

- Table 62 — "Container requirements" for type `XX::value_type`

- Table 65 — "Allocator-aware container requirements" for type `allocator_type`

- Table 69 — "Associative container requirements" for types `X::value_type` and `X::key_compare`

- Table 70 — "Unordered associative container requirements" for types `X::value_type` and `X::key_equal`

Instead of replacing these elements usages for these places by extra wording to reach the same effects I recommend to update instead 16.3.2.4 [structure.specifications] to ensure that requirement-expressing elements are defined in a way that it also allows to express requirements imposed on types by these elements to standardize "existing practice".

Considering details, it seems obvious that Mandates:, Expects: as well as Requires: are "suitable" to be defined for types (With the acceptance of P1463R1 there are now also Mandates: for types such as Table 65 — "Allocator-aware container requirements" for type `allocator_type`).

For Constraints: the meaning would not be so clear: Should it mean that there is conditionally a type defined or not? According to the submitters knowledge there are currently no known examples for Constraints: to specify constraint on types, therefore I'm suggesting to restrict this extension to Mandates:, Expects:, and Requires: alone.

[2019-03-15 Priority set to 3 after reflector discussion]

[2019-03-15; Daniel comments and provides wording]

During the preparation of the wording for this issue it was found that we should allow Remarks: elements to be used for other things than functions. One example of imposed restrictions can be found in 17.12.3 [cmp.common]:

>     template<class... Ts>
>     struct common_comparison_category {
>       using type = see below;
>     };

> -2- Remarks: The member typedef-name `type` denotes the common comparison type (11.10.3 [class.spaceship]) of `Ts...`, the expanded parameter pack. […]

The discussion of this issue speaks of "type" restrictions (versus the specified restrictions on functions), because even the non-type template argument restrictions of 22.3.4 [pair.astuple] appear in the context of a member type specification, but there are examples where not really a single (member) type is involved, e.g. in the 22.4.7 [tuple.helper] example mentioned above.

Another example is when such elements are used for the specification of template specializations, e.g. in 22.4.7 [tuple.helper]:

>     template<class T> struct tuple_size;

> > -1- Remarks: All specializations of `tuple_size` shall satisfy the Cpp17UnaryTypeTrait requirements (21.3.2 [meta.rqmts]) with a base characteristic of `integral_constant<size_t, N>` for some `N`.

Besides class template specializations, a second relevant use-case is the specification of member types (Which are not necessarily part of a template), typically within the requirement tables, e.g. in Table 62 — "Container requirements"'s entry `X::value_type`:

> Requires: `T` is Cpp17Erasable from `X`

The suggested wording tries to cover the generalization by means of the term "non-function entities" in addition to the existing functions to prevent being enforced to enumerate all entities to which the extended rules apply.

Previous resolution [SUPERSEDED]:

> This wording is relative to N4810.

> 1. Change 16.3.2.4 [structure.specifications], as indicated:

>    > -3- Descriptions of function semantics contain the following elements (as appropriate); some of these elements may also appear in the description of non-function entities as denoted below: (footnote […])

>    > 1. (3.1) — Requires: the preconditions imposed on a non-function entity, or for calling the function.

>    > 2. (3.2) — Constraints: […]

>    > 3. (3.3) — Mandates: the conditions that, if not met, render the program ill-formed. [Example: An implementation might express such a condition via the constant-expression in a static_assert-declaration (Clause 9). If the diagnostic is to be emitted only after the function has been selected by overload resolution, an implementation might express such a condition via a constraint-expression (13.5.3 [temp.constr.decl]) and also define the function as deleted. — end example]

>    > 4. (3.4) — Expects: the conditions (sometimes termed preconditions) imposed on a non-function entity, or that the function assumes to hold whenever it is called. [Example: An implementation might express such conditions via an attribute such as `[[expects]]` ( [dcl.attr.contract]) on a function declaration. However, some such conditions might not lend themselves to expression via code. — end example]

>    > 5. […]

>    > 6. (3.11) — Remarks: additional semantic constraints on the function.

>    > 7. […]

> 2. Change 99 [res.on.required], as indicated:

>    > -1- Violation of any preconditions specified in a function's Requires: element results in undefined behavior unless the function's Throws: element specifies throwing an exception when the a function's precondition is violated.

>    > -2- Violation of any preconditions specified in an function's Expects: element results in undefined behavior.

[2020-05-01; Daniel comments and adjusts wording to recent working draft]

It should be pointed out that the originally referred to Expects: element has since then be renamed to Preconditions: and that the Requires: element does now only occur in annex D.

[2020-06-11; Jonathan comments]

This issue also affects some type traits such as `alignment_of` and `make_signed`/`make_unsigned`. In addition to clarifying what Mandates: means on a non-function we need to decide exactly what is being mandated in the type traits. Is instantiating the class template ill-formed, or just odr-using the nested `type` or `value` member?

Proposed resolution:

This wording is relative to N4861.

1. Change 16.3.2.4 [structure.specifications], as indicated:

   > -3- Descriptions of function semantics contain the following elements (as appropriate); some of these elements may also appear in the description of non-function entities as denoted below: (footnote […])

   > 1. (3.1) — Constraints: […]

   > 2. (3.2) — Mandates: the conditions that, if not met, render the program ill-formed. [Example: An implementation might express such a condition via the constant-expression in a static_assert-declaration (9.1 [dcl.pre]). If the diagnostic is to be emitted only after the function has been selected by overload resolution, an implementation might express such a condition via a constraint-expression (13.5.3 [temp.constr.decl]) and also define the function as deleted. — end example]

   > 3. (3.3) — Preconditions: the conditions imposed on a non-function entity, or that the function assumes to hold whenever it is called.

   > 4. […]

   > 5. (3.10) — Remarks: additional semantic constraints on the function.

   > 6. […]

2. Change [res.on.expects], as indicated:

   > -1- Violation of any preconditions specified in a function's Preconditions: element results in undefined behavior.

3. Change D.10 [depr.res.on.required], as indicated:

   > [Drafting note: Interestingly, albey the Requires: element has nearly vanished, the issue is still relevant, see D.15 [depr.meta.types]]

   > -1- Violation of any preconditions specified in a function's Requires: element results in undefined behavior unless the function's Throws: element specifies throwing an exception when the a function's precondition is violated.