Title
scoped_allocator_adaptor constructors must be constrained
Status
c++17
Section
[allocator.adaptor.cnstr]
Submitter
Jonathan Wakely

Created on 2016-10-14.00:00:00 last changed 90 months ago

Messages

Date: 2016-11-21.05:09:01

Proposed resolution:

This wording is relative to N4606.

  1. Modify [allocator.adaptor.cnstr] by converting "Requires" elements to "Remarks: shall not participate ..." constraints as shown:

    template <class OuterA2>
      scoped_allocator_adaptor(OuterA2&& outerAlloc,
                               const InnerAllocs&... innerAllocs) noexcept;
    

    -2- Requires: OuterAlloc shall be constructible from OuterA2.

    -3- Effects: Initializes the OuterAlloc base class with std::forward<OuterA2>(outerAlloc) and inner with innerAllocs... (hence recursively initializing each allocator within the adaptor with the corresponding allocator from the argument list).

    -?- Remarks: This constructor shall not participate in overload resolution unless is_constructible_v<OuterAlloc, OuterA2> is true.

    […]

    template <class OuterA2>
      scoped_allocator_adaptor(const scoped_allocator_adaptor<OuterA2,
                               InnerAllocs...>& other) noexcept;
    

    -6- Requires: OuterAlloc shall be constructible from OuterA2.

    -7- Effects: Initializes each allocator within the adaptor with the corresponding allocator from other.

    -?- Remarks: This constructor shall not participate in overload resolution unless is_constructible_v<OuterAlloc, const OuterA2&> is true.

    template <class OuterA2>
      scoped_allocator_adaptor(scoped_allocator_adaptor<OuterA2,
                               InnerAllocs...>&& other) noexcept;
    

    -8- Requires: OuterAlloc shall be constructible from OuterA2.

    -9- Effects: Initializes each allocator within the adaptor with the corresponding allocator rvalue from other.

    -?- Remarks: This constructor shall not participate in overload resolution unless is_constructible_v<OuterAlloc, OuterA2> is true.

Date: 2016-11-15.00:00:00

[ 2016-11-12, Issaquah ]

Sat AM: Priority 0; move to Ready

Billy to open another issue about the confusion with the ctor

Date: 2016-10-14.00:00:00

The templated constructors of scoped_allocator_adaptor need to be constrained, otherwise uses-allocator construction gives the wrong answer and causes errors for code that should compile.

Consider two incompatible allocator types:

template<class T> struct Alloc1 { ... };
template<class T> struct Alloc2 { ... };
static_assert(!is_convertible_v<Alloc1<int>, Alloc2<int>>);

The unconstrained constructors give this bogus answer:

template<class T> using scoped = scoped_allocator_adaptor<T>;
static_assert(is_convertible_v<scoped<Alloc1<int>>, scoped<Alloc2<int>>>);

This causes uses_allocator to give the wrong answer for any specialization involving incompatible scoped_allocator_adaptors, which makes scoped_allocator_adaptor::construct() take an ill-formed branch e.g.

struct X 
{
  using allocator_type = scoped<Alloc2<int>>;
  X(const allocator_type&);
  X();
};
scoped<Alloc1<int>>{}.construct((X*)0);

This fails to compile, because uses_allocator<X, scoped_allocator_adaptor<Alloc2<int>>> is true, so the allocator is passed to the X constructor, but the conversion fails. The error is outside the immediate context, and so is a hard error.

History
Date User Action Args
2017-07-30 20:15:43adminsetstatus: wp -> c++17
2017-03-05 23:41:16adminsetstatus: ready -> wp
2016-11-21 05:09:01adminsetmessages: + msg8665
2016-11-21 05:09:01adminsetstatus: new -> ready
2016-10-15 12:31:44adminsetmessages: + msg8563
2016-10-14 00:00:00admincreate