801. tuple and pair trivial members

Section: 23.5 [tuple] Status: Resolved Submitter: Lawrence Crowl Opened: 2008-02-18 Last modified: 2016-02-10

Priority: Not Prioritized

View all other issues in [tuple].

View all issues with Resolved status.


Classes with trivial special member functions are inherently more efficient than classes without such functions. This efficiency is particularly pronounced on modern ABIs that can pass small classes in registers. Examples include value classes such as complex numbers and floating-point intervals. Perhaps more important, though, are classes that are simple collections, like pair and tuple. When the parameter types of these classes are trivial, the pairs and tuples themselves can be trivial, leading to substantial performance wins.

The current working draft make specification of trivial functions (where possible) much easer through defaulted and deleted functions. As long as the semantics of defaulted and deleted functions match the intended semantics, specification of defaulted and deleted functions will yield more efficient programs.

There are at least two cases where specification of an explicitly defaulted function may be desirable.

First, the std::pair template has a non-trivial default constructor, which prevents static initialization of the pair even when the types are statically initializable. Changing the definition to

pair() = default;

would enable such initialization. Unfortunately, the change is not semantically neutral in that the current definition effectively forces value initialization whereas the change would not value initialize in some contexts.

** Does the committee confirm that forced value initialization was the intent? If not, does the committee wish to change the behavior of std::pair in C++0x?

Second, the same default constructor issue applies to std::tuple. Furthermore, the tuple copy constructor is current non-trivial, which effectively prevents passing it in registers. To enable passing tuples in registers, the copy constructor should be make explicitly defaulted. The new declarations are:

tuple() = default;
tuple(const tuple&) = default;

This changes is not implementation neutral. In particular, it prevents implementations based on pointers to the parameter types. It does however, permit implementations using the parameter types as bases.

** How does the committee wish to trade implementation efficiency versus implementation flexibility?

[ Bellevue: ]

General agreement; the first half of the issue is NAD.

Before voting on the second half, it was agreed that a "Strongly Favor" vote meant support for trivial tuples (assuming usual requirements met), even at the expense of other desired qualities. A "Weakly Favor" vote meant support only if not at the expense of other desired qualities.

Concensus: Go forward, but not at expense of other desired qualities.

It was agreed to Alisdair should fold this work in with his other pair/tuple action items, above, and that issue 801 should be "open", but tabled until Alisdair's proposals are disposed of.

[ 2009-05-27 Daniel adds: ]

This is partly solved by 1117.

[ 2009-07 Frankfurt: ]

Wait for dust to settle from fixing exception safety problem with rvalue refs.

[ 2009-07-20 Alisdair adds: ]

Basically, this issue is what should we do with the default constructor for pairs and tuples of trivial types. The motivation of the issue was to force static initialization rather than dynamic initialization, and was rejected in the case of pair as it would change the meaning of existing programs. The advice was "do the best we can" for tuple without changing existing meaning.

Frankfurt seems to simply wait and see the resolution on no-throw move constructors, which (I believe) is only tangentially related to this issue, but as good as any to defer until Santa Cruz.

Looking again now, I think constant (static) initialization for pair can be salvaged by making the default construct constexpr. I have a clarification from Core that this is intended to work, even if the constructor is not trivial/constexpr, so long as no temporaries are implied in the process (even if elided).

[ 2009-10 Santa Cruz: ]

Leave as open. Alisdair to provide wording.

[ 2010 Pittsburgh: ]

We believe this may be NAD Editorial since both pair and tuple now have constexpr default constructors, but we're not sure.

[ 2010 Rapperswil: ]

Daniel believes his pair/tuple paper will resolve this issue. constexpr will allow static initialization, and he is already changing the move and copy constructors to be defaulted.

[ 2010-10-24 Daniel adds: ]

The proposed resolution of n3140 should resolve this issue.

Proposed resolution:

See n3140.