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.