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

### 3158. `tuple(allocator_arg_t, const Alloc&)` should be conditionally explicit

Section: 20.5.3.1 [tuple.cnstr] Status: C++20 Submitter: Jonathan Wakely Opened: 2018-08-21 Last modified: 2021-02-25

Priority: 3

View other active issues in [tuple.cnstr].

View all other issues in [tuple.cnstr].

View all issues with C++20 status.

Discussion:

`std::tuple`'s allocator-extended constructors say "Effects: Equivalent to the preceding constructors except that each element is constructed with uses-allocator construction". That's not true for the first one, as shown by:

>     #include <tuple>

>     struct X { explicit X() { } };

>     std::tuple<X> f() { return {}; }
>     std::tuple<X> g() { return { std::allocator_arg, std::allocator<int>{} }; }

The function `f()` doesn't compile because of the explicit constructor, but `g()` does, despite using the same constructor for `X`. The conditional explicit-ness is not equivalent.

Also, the editor requested that we change "implicitly default-constructible" to use words that mean something. He suggested "copy-list-initializable from an empty list".

[2018-09 Reflector prioritization]

Set Priority to 3

[2019-02; Kona Wednesday night issue processing]

Status to Ready

Proposed resolution:

This wording is relative to N4762.

1. Modify 20.5.3 [tuple.tuple], class template `tuple` synopsis, as indicated:

   >     […]
   >     // allocator-extended constructors
   >     template<class Alloc>
   >       explicit(see below) tuple(allocator_arg_t, const Alloc& a);
   >     template<class Alloc>
   >       explicit(see below) tuple(allocator_arg_t, const Alloc& a, const Types&...);
   >     […]

2. Modify 20.5.3.1 [tuple.cnstr], as indicated:

   >     explicit(see below) constexpr tuple();

   > > -5- Effects: Value-initializes each element.

   > > -6- Remarks: This constructor shall not participate in overload resolution unless `is_default_constructible_v<Ti>` is `true` for all `i`. [Note: This behavior can be implemented by a constructor template with default template arguments. — end note] The expression inside `explicit` evaluates to `true` if and only if `Ti` is not implicitly default-constructible copy-list-initializable from an empty list for at least one `i`. [Note: This behavior can be implemented with a trait that checks whether a `const Ti&` can be initialized with `{}`. — end note]

   > […]

   >     template<class Alloc>
   >       explicit(see below) tuple(allocator_arg_t, const Alloc& a);
   >     template<class Alloc>
   >       explicit(see below) tuple(allocator_arg_t, const Alloc& a, const Types&...);
   >     […]
   >     template<class Alloc, class U1, class U2>
   >       explicit(see below) tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&&);

   > > -25- Requires: `Alloc` shall satisfy the `Cpp17Allocator` requirements (Table 33).

   > > […]