Title
tuple{allocator_arg_t, an_allocator}
Status
open
Section
[tuple.cnstr]
Submitter
Jonathan Wakely

Created on 2018-08-18.00:00:00, last changed 2018-10-01.03:18:34.

Messages

Date: 2018-10-01.03:18:34

Proposed resolution:

This wording is relative to N4762.

  1. Modify [tuple.cnstr] as indicated:

    template<class... UTypes> explicit(see below) constexpr tuple(UTypes&&... u);
    

    -9- Effects: Initializes the elements in the tuple with the corresponding value in std::forward<UTypes>(u).

    -10- Remarks: This constructor shall not participate in overload resolution unless sizeof...(Types) == sizeof...(UTypes) and sizeof...(Types) >= 1 and is_constructible_v<Ti, Ui&&> is true for all i and (sizeof...(Types) != 2 || !is_same_v<remove_cvref_t<U0>, allocator_arg_t>). The expression inside explicit is equivalent to:

    !conjunction_v<is_convertible<UTypes, Types>...>

Date: 2018-10-01.03:18:34

[ 2018-09 Reflector prioritization ]

Set Priority to 3

Date: 2018-11-12.05:21:03

[ 2018-08 Batavia Friday ]

Tim Song found a 3-element case of this issue. Status back to 'Open'

tuple<any,any,any>(allocator_arg_t, a, tuple)

Date: 2018-08-22.12:55:05

[ 2018-08 Batavia Monday issue prioritization ]

Priority set to 0, status to 'Tentatively Ready'. Alisdair to write a paper about SFINAE constraints on the Allocator-aware tuple constructors.

Date: 2018-08-15.00:00:00

[ 2018-08-20, Daniel comments ]

The wording changes by this issue are very near to those suggested for LWG 3121.

Date: 2018-08-18.17:38:43

For a 2-element std::tuple, attempting to call the "allocator-extended default constructor" might actually pass the allocator_arg tag and the allocator to the tuple element constructors:

tuple<any, any> t{allocator_arg, allocator<int>{}};
assert(std::get<0>(t).has_value());

This assertion should pass according to the standard, but users might expect the elements to be default constructed. If you really wanted to construct the elements with the tag and the allocator, you could do:

tuple<any, any> t{{allocator_arg}, {allocator<int>{}}};

or

tuple<any, any> t{tuple<allocator_arg_t, allocator<int>>{allocator_arg, allocator<int>{}}};

The deduction guides for std::tuple always treat {allocator_arg_t, an_allocator} as the allocator-extended default constructor, so this creates an empty tuple:

tuple t{allocator_arg, allocator<int>{}};

And this is needed to create tuple<any, any>:

tuple t{allocator_arg, allocator<int>{}, any{}, any{}};

The proposed resolution seems consistent with that, always calling an allocator-extended constructor for {allocator_arg_t, a}, instead of the tuple(UTypes&&...) constructor.

Ville Voutilainen:

This was discussed in this reflector thread, where Andrzej convinced me to change libstdc++ tuple.

History
Date User Action Args
2018-10-01 03:18:34adminsetmessages: + msg10148
2018-08-27 15:01:43adminsetmessages: + msg10138
2018-08-27 15:01:43adminsetstatus: ready -> open
2018-08-22 12:55:05adminsetmessages: + msg10102
2018-08-22 12:55:05adminsetstatus: new -> ready
2018-08-20 15:00:41adminsetmessages: + msg10084
2018-08-18 16:57:11adminsetmessages: + msg10076
2018-08-18 00:00:00admincreate