https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124787

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |RESOLVED
         Resolution|---                         |INVALID

--- Comment #1 from Jonathan Wakely <redi at gcc dot gnu.org> ---
Your allocator types do not meet the Allocator requirements.

It must be possible to construct my_allocator2<T> from my_allocator2<U>, so you
need to add converting constructors:

    my_allocator1() = default;

    template<typename U>
    my_allocator1(const my_allocator1<U>&) { }

and:

    my_allocator2() = default;

    template<typename U>
    my_allocator2(const my_allocator2<U>&) { }


Your example works for std::vector because vector does not rebind the allocator
to a different type, so it only tries to construct my_allocator2<int> from
my_allocator2<int>, which uses the implicit copy constructor. That works fine.

It works for std::list because the std::list implementation only needs to
default-construct my_allocator2<_Node>, and your type supports a default
constructor. It would fail for std::list if you supplied an allocator to the
list constructor, so that it doesn't just default construct its own allocator:

    my_allocator1<int> a1;
    std::list<int, my_allocator1<int>> l1(a1);

This fails to compile.

It doesn't work for std::deque because even without passing an allocator to the
deque constructor, it always wants to use a converting constructor for the
rebound allocator. It default constructs my_allocator2<int> and then makes a
copy of that to get a my_allocator2<int*>, which requires the converting
constructor.

So this is a bug in your code, not in libstdc++.

The reason it "works" for my_allocator1 but not my_allocator2 is due to the
C++20 rules on aggregates and parenthsized aggregate initialization.

Reply via email to