This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of Resolved status.
1383. Inconsistent defaulted move/copy members in pair and tuple
Section: 22.3 [pairs], 22.4 [tuple] Status: Resolved
Submitter: INCITS Opened: 2010-08-25 Last modified: 2016-01-28
Priority: Not Prioritized
View all other issues in [pairs].
View all issues with Resolved status.
Discussion:
Addresses US-97
pair's class definition in N3092 22.3.2 [pairs.pair]
contains "pair(const pair&) = default;" and
"pair& operator=(pair&& p);". The latter is described by
22.3.2 [pairs.pair] p.12-13.
"pair(const pair&) = default;" is a user-declared explicitly defaulted
copy constructor. According to [class.copy]/10, this inhibits
the implicitly-declared move constructor. pair should be move constructible.
( [class.copy]/7 explains that "pair(pair<U, V>&& p)"
will never be instantiated to move pair<T1, T2> to pair<T1, T2>.)
"pair& operator=(pair&& p);" is a user-provided move
assignment operator (according to 9.5.2 [dcl.fct.def.default]/4: "A
special member function is user-provided if it is user-declared and not explicitly defaulted
on its first declaration."). According to [class.copy]/20, this inhibits
the implicitly-declared copy assignment operator. pair
should be copy assignable, and was in C++98/03. (Again,
[class.copy]/7 explains that "operator=(const pair<U, V>& p)"
will never be instantiated to copy pair<T1, T2> to pair<T1, T2>.)
Additionally, "pair& operator=(pair&& p);" is
unconditionally defined, whereas according to [class.copy]/25,
defaulted copy/move assignment operators are defined as
deleted in several situations, such as when non-static data
members of reference type are present.
If "pair(const pair&) = default;" and "pair& operator=(pair&& p);"
were removed from pair's class definition in 22.3.2 [pairs.pair] and from
22.3.2 [pairs.pair]/12-13, pair would
receive implicitly-declared copy/move constructors and
copy/move assignment operators, and [class.copy]/25 would
apply. The implicitly-declared copy/move constructors
would be trivial when T1 and T2 have trivial copy/move
constructors, according to [class.copy]/13, and similarly for the
assignment operators, according to [class.copy]/27. Notes could
be added as a reminder that these functions would be
implicitly-declared, but such notes would not be necessary
(the Standard Library specification already assumes a
high level of familiarity with the Core Language, and
casual readers will simply assume that pair is copyable
and movable).
Alternatively, pair could be given explicitly-defaulted
copy/move constructors and copy/move assignment
operators. This is a matter of style.
tuple is also affected. tuple's class definition in 22.4 [tuple] contains:
tuple(const tuple&) = default;
tuple(tuple&&);
tuple& operator=(const tuple&);
tuple& operator=(tuple&&);
They should all be removed or all be explicitly-defaulted,
to be consistent with pair. Additionally, 22.4.4.1 [tuple.cnstr]/8-9 specifies the
behavior of an explicitly defaulted function, which is currently inconsistent with
pair.
[
Resolution proposed by ballot comment:
]
Either remove "pair(const pair&) = default;" and
"pair& operator=(pair&& p);" from pair's class
definition in 22.3.2 [pairs.pair] and from 22.3.2 [pairs.pair] p.12-13, or
give pair explicitly-defaulted copy/move constructors and copy/move assignment operators.
Change tuple to match.
[
2010-10-24 Daniel adds:
]
Accepting n3140 would solve this issue:
The move/copy constructor will be defaulted, but the corresponding assignment operators need a non-default implementation
because they are supposed to work for references as well.
Proposed resolution:
See n3140.