3155. tuple<any, any>{allocator_arg_t, an_allocator}

Section: [tuple.cnstr] Status: Resolved Submitter: Jonathan Wakely Opened: 2018-08-18 Last modified: 2021-10-23 03:16:45 UTC

Priority: 3

View other active issues in [tuple.cnstr].

View all other issues in [tuple.cnstr].

View all issues with Resolved status.


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>{}};

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>{}}};


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.

[2018-08-20, Daniel comments]

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

[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.

[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)

[2018-09 Reflector prioritization]

Set Priority to 3

Previous resolution [SUPERSEDED]:

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>...>

[2021-08-20; LWG telecon]

Status changed to Tentatively Resolved, by 3121.

[2021-10-23 Resolved by 3121, approved at October 2021 virtual plenary. Status changed: Tentatively Resolved → Resolved.]

Proposed resolution:

This issue is resolved by the resolution of issue 3121.