Title
tuple(allocator_arg_t, const Alloc&) should be conditionally explicit
Status
new
Section
[tuple.cnstr]
Submitter
Jonathan Wakely

Created on 2018-08-21.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.

  • Modify [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&...);
    […]
    
  • Modify [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).

    […]

Date: 2018-10-01.03:18:34

[ 2018-09 Reflector prioritization ]

Set Priority to 3

Date: 2018-08-21.00:00:00

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

History
Date User Action Args
2018-10-01 03:18:34adminsetmessages: + msg10114
2018-09-09 11:57:27adminsetmessages: + msg10108
2018-08-21 00:00:00admincreate