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

### 3382. NTTP for `pair` and `array`

Section: 22.3.2 [pairs.pair], 24.3.7 [array] Status: C++20 Submitter: Barry Revzin Opened: 2020-01-27 Last modified: 2021-02-25

Priority: 2

View other active issues in [pairs.pair].

View all other issues in [pairs.pair].

View all issues with C++20 status.

Discussion:

We had this NB ballot issue, to ensure that `std::array` could be a NTTP. But after P1907, we still need some kind of wording to ensure that `std::array` (and also `std::pair`) have no extra private members or base classes.

This is similar to LWG 3373 — maybe we just need to add:

> The class template `pair`/`array` has the data members specified above. It has no base classes or data members other than those specified.

[2020-02 Prioritized as P2 Monday morning in Prague]

Previous resolution [SUPERSEDED]:

> This wording is relative to N4849.

> 1. Modify 22.3.2 [pairs.pair] as indicated:

>    > -1- Constructors and member functions of `pair` do not throw exceptions unless one of the element-wise operations specified to be called for that operation throws an exception.

>    > -2- The defaulted move and copy constructor, respectively, of `pair` is a constexpr function if and only if all required element-wise initializations for copy and move, respectively, would satisfy the requirements for a constexpr function.

>    > -3- If `(is_trivially_destructible_v<T1> && is_trivially_destructible_v<T2>)` is `true`, then the destructor of `pair` is trivial.

>    > -?- The class template `pair` has the data members specified above. It has no base classes or data members other than those specified.

> 2. Modify 24.3.7.1 [array.overview] as indicated:

>    > -1- The header `<array>` defines a class template for storing fixed-size sequences of objects. An `array` is a contiguous container (24.2.2.1 [container.requirements.general]). An instance of `array<T, N>` stores `N` elements of type `T`, so that `size() == N` is an invariant.

>    > -2- An `array` is an aggregate (9.4.2 [dcl.init.aggr]) that can be list-initialized with up to `N` elements whose types are convertible to `T`.

>    > -3- An `array` meets all of the requirements of a container and of a reversible container (24.2 [container.requirements]), except that a default constructed `array` object is not empty and that `swap` does not have constant complexity. An `array` meets some of the requirements of a sequence container (24.2.4 [sequence.reqmts]). Descriptions are provided here only for operations on `array` that are not described in one of these tables and for operations where there is additional semantic information.

>    > -?- The class template `array` has the data members specified in subclauses 24.3.7.1 [array.overview] and 24.3.7.5 [array.zero]. It has no base classes or data members other than those specified.

>    > -4- […]

[2020-02-13, Prague]

Tim Song and Tomasz were trying to come up with general wording that could be reused for both `pair` and `array` (and other types). They suggest that if it should be in scope for C++20, it would be better to provide non-general wording for `pair` and `array` (that is easier to get right).

For completeness (and future wording) the generalized wording is included. The definition of structurally compatible with:

> The type `T` is structurally compatible with `subs`, if for the values `t1` and `t2` of type `T`:

> - `T` is a structural type (13.2 [temp.param]) if the types of subobjects of `t1` designated by `subs` are all structural types.

> - `t1` is template-argument-equivalent (13.6 [temp.type]) to `t2`, if and only if, for each subject designed by `subs`, the value of subobject of `t1` is template-argument-equivalent to the value of the correponding subobject of `t2`.

Then changes for `array`/`pair` would then look like:

> `pair<T, U>` is structurally compatible (<some-reference>) with `first` and `second`.

> `array<T, N>` is structurally compatible with its elements (if any).

[2020-02 Status to Immediate on Friday morning in Prague.]

Proposed resolution:

This wording is relative to N4849.

1. Modify 22.3.2 [pairs.pair] as indicated:

   > -1- Constructors and member functions of `pair` do not throw exceptions unless one of the element-wise operations specified to be called for that operation throws an exception.

   > -2- The defaulted move and copy constructor, respectively, of `pair` is a constexpr function if and only if all required element-wise initializations for copy and move, respectively, would satisfy the requirements for a constexpr function.

   > -3- If `(is_trivially_destructible_v<T1> && is_trivially_destructible_v<T2>)` is `true`, then the destructor of `pair` is trivial.

   > -?- `pair<T, U>` is a structural type (13.2 [temp.param]) if `T` and `U` are both structural types. Two values `p1` and `p2` of type `pair<T, U>` are template-argument-equivalent (13.6 [temp.type]) if and only if `p1.first` and `p2.first` are template-argument-equivalent and `p1.second` and `p2.second` are template-argument-equivalent.

2. Modify 24.3.7.1 [array.overview] as indicated:

   > -1- The header `<array>` defines a class template for storing fixed-size sequences of objects. An `array` is a contiguous container (24.2.2.1 [container.requirements.general]). An instance of `array<T, N>` stores `N` elements of type `T`, so that `size() == N` is an invariant.

   > -2- An `array` is an aggregate (9.4.2 [dcl.init.aggr]) that can be list-initialized with up to `N` elements whose types are convertible to `T`.

   > -3- An `array` meets all of the requirements of a container and of a reversible container (24.2 [container.requirements]), except that a default constructed `array` object is not empty and that `swap` does not have constant complexity. An `array` meets some of the requirements of a sequence container (24.2.4 [sequence.reqmts]). Descriptions are provided here only for operations on `array` that are not described in one of these tables and for operations where there is additional semantic information.

   > -?- `array<T, N>` is a structural type (13.2 [temp.param]) if `T` is a structural type. Two values `a1` and `a2` of type `array<T, N>` are template-argument-equivalent (13.6 [temp.type]) if and only if each pair of corresponding elements in `a1` and `a2` are template-argument-equivalent.

   > -4- […]