https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124787
--- Comment #2 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Jonathan Wakely from comment #1)
> The reason it "works" for my_allocator1 but not my_allocator2 is due to the
> C++20 rules on aggregates and parenthsized aggregate initialization.
Specifically, this compiles in C++20 (but not in earlier standards) even
without a converting constructor:
my_allocator1<int> a1;
my_allocator1<short> aa1(a1);
The reason is that my_allocator1<short> is an aggregate in C++20, because you
didn't define any constructors, and so aa1(a1) is aggregate initialization in
C++20.
So a1 is interpreted as an initializer for the std::allocator<short> base
class, which is valid because a1 can be converted to std::allocator<int>& via a
derived-to-base conversion, and then uses the converting constructor,
std::allocator<short>::allocator<int>(const std::allocator<int>&)
But this doesn't compile:
my_allocator2<int> a2;
my_allocator2<short> aa2(a2);
Again, my_allocator2 is an aggregate, and so aa2(a2) attempts to do aggregate
initialization, interpreting a2 as an initializer for the my_allocator1<short>
base class. But because you didn't provide a converting constructor, you cannot
initialize the base class from a2.