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

### 2068. `std::pair` not C++03-compatible with defaulted copy c'tor

Section: 20.4.2 [pairs.pair] Status: NAD Submitter: Daniel Krügler Opened: 2011-06-18 Last modified: 2016-01-28

Priority: Not Prioritized

View other active issues in [pairs.pair].

View all other issues in [pairs.pair].

View all issues with NAD status.

Discussion:

The specification of the copy semantics of the C++03 version of `std::pair` is defined by the class synopsis in [lib.pairs]:

>     template <class T1, class T2>
>     struct pair {
>       typedef T1 first_type;
>       typedef T2 second_type;

>       T1 first;
>       T2 second;
>       pair();
>       pair(const T1& x, const T2& y);
>       template<class U, class V> pair(const pair<U, V> &p);
>     };

The effect of this specification is, that the copy constructor is compiler-declared with the proper form depending on the contained member types. In particular, the instantiation of `pair` is well-formed with an element type that has a copy constructor with non-const first parameter type like specialzations of `auto_ptr` or any user-defined type like the following one:

>     struct A {
>       A(A&){}
>     };

In contrast to container types which require `CopyConstructible` value types, the C++03 `pair` does support these, albeit unusual, element types.

The FDIS version of the `std::pair` specification does specify the same semantics by defaulting the copy and move constructor in 20.4.2 [pairs.pair]:

>     template <class T1, class T2>
>     struct pair {
>       typedef T1 first_type;
>       typedef T2 second_type;

>       T1 first;
>       T2 second;
>       pair(const pair&) = default;
>       pair(pair&&) = default;
>       pair();
>       […]
>     };

But according to the current core rules this makes the instantiation of e.g. `std::pair<A, int>` ill-formed, because of the `const` mismatch of the compiler-declared form of the copy constructor with that of the defaulted declaration.

Unfortunately there seems to be no simple library solution for this problem. If the defaulted declarations were removed, both copy c'tor and move c'tor would be deleted, because there exist user-declared copy assignment and move assignment operators in the FDIS. But these operations need to be user-defined to realize the wanted semantics of these operations for element types that are reference types. If core rules would not be changed to fix that, I see the following options:

1. Intentionally decide to break the support for element types with non-const copy c'tors in `pair`.
2. User-declare both copy and move ctor to at least support the instantiation of the `pair` specializations, but this would still not allow to copy them by the copy constructor.
3. User-declare both the const and non-const copy ctors, the move ctor, and additionally the non-const copy assignment operator to support the instantiation of the `pair` specializations and of these members. This would support all element types as it did in C++03, but all copy/move members would be non-trivial.
4. Intentionally decide to give up support for element types that are references for `pair`, but still keep the allocator support with the effect of removing all declarations of the special copy/move members. User code that needs to use `tuple` instead. But this would be a rather drastic step requiring further corrections of the draft, e.g. a change of the signature of the algorithm `minmax` (not the overload with the `initializer_list`) with a different return type.

This problem does not extend as backward-compatibility problem to `tuple`, because the TR1 specification did explicitly declare copy constructor and copy assignment operator via the "normal" form:

>     tuple(const tuple&);
>     tuple& operator=(const tuple&);

[Bloomington, 2011]

Closed as NAD.

This is an unfortunate change of behavior between C++03 and C++11, but is consistent with `tuple`. There is no desire to go to lengths supporting types like `auto_ptr` now that rvalue references are in the language.

There may be an issue for Core/EWG to look at, so that some simple `=default` syntax could be used that would do the right thing. If such a facility became availabile, LWG might revisit this issue.

Proposed resolution: