On Fri, Feb 13, 2026 at 11:13 AM Tomasz Kamiński <[email protected]> wrote:
> Presence implicit conversion from int to it's allocator, makes constructing > string from rvalue of same string type and int ambiguous, as none of > following > candidates is better: > basic_string(basic_string&&, allocator_type) > // conversion from int to allocator for second argument > basic_string(const basic_string&, int, allocator_type) > // reference adjustment for first argument > > This makes __gnu_test:uneq_allocator(int) constructor explicit, to avoid > above issues. > > libstdc++-v3/ChangeLog: > > * testsuite/20_util/scoped_allocator/construct_pair_c++2a.cc > (__gnu_test::uneq_allocator(int)): Declare as explicit. > * testsuite/std/memory/indirect/ctor.cc: Construct uneq_allocator > from int explicitly. > * testsuite/std/memory/polymorphic/ctor.cc: Likewise. > * testsuite/std/memory/polymorphic/ctor_poly.cc: Likewise. > * testsuite/util/testsuite_allocator.h: Likewise. > > Reviewed-by: Jonathan Wakely <[email protected]> > Signed-off-by: Tomasz Kamiński <[email protected]> > --- > This is v2, that fixes commit descriptions. Pushed to trunk. > .../scoped_allocator/construct_pair_c++2a.cc | 12 ++++---- > .../testsuite/std/memory/indirect/ctor.cc | 29 +++++++++++-------- > .../testsuite/std/memory/polymorphic/ctor.cc | 27 ++++++++++------- > .../std/memory/polymorphic/ctor_poly.cc | 18 +++++++----- > .../testsuite/util/testsuite_allocator.h | 2 +- > 5 files changed, 51 insertions(+), 37 deletions(-) > > diff --git > a/libstdc++-v3/testsuite/20_util/scoped_allocator/construct_pair_c++2a.cc > b/libstdc++-v3/testsuite/20_util/scoped_allocator/construct_pair_c++2a.cc > index ecc26cb5a63..4eb174a89f3 100644 > --- > a/libstdc++-v3/testsuite/20_util/scoped_allocator/construct_pair_c++2a.cc > +++ > b/libstdc++-v3/testsuite/20_util/scoped_allocator/construct_pair_c++2a.cc > @@ -39,10 +39,10 @@ void > test01() > { > using value_type = std::pair<std::pair<X, int>, std::pair<int, X>>; > - using scoped_alloc > - = > std::scoped_allocator_adaptor<__gnu_test::uneq_allocator<value_type>>; > + using uneq_alloc = __gnu_test::uneq_allocator<value_type>; > + using scoped_alloc = std::scoped_allocator_adaptor<uneq_alloc>; > > - const scoped_alloc a(10); > + const scoped_alloc a(uneq_alloc(10)); > std::vector<value_type, scoped_alloc> v(a); > VERIFY( v.get_allocator().get_personality() == a.get_personality() ); > > @@ -65,11 +65,11 @@ void > test02() > { > using value_type = std::pair<std::pair<X, int>, std::pair<int, X>>; > + using uneq_alloc = __gnu_test::uneq_allocator<value_type>; > using scoped_alloc > - = > std::scoped_allocator_adaptor<__gnu_test::uneq_allocator<value_type>, > - X::allocator_type>; > + = std::scoped_allocator_adaptor<uneq_alloc, X::allocator_type>; > > - const scoped_alloc a(10, 20); > + const scoped_alloc a(uneq_alloc(10), X::allocator_type(20)); > std::vector<value_type, scoped_alloc> v(a); > VERIFY( v.get_allocator().get_personality() == a.get_personality() ); > > diff --git a/libstdc++-v3/testsuite/std/memory/indirect/ctor.cc > b/libstdc++-v3/testsuite/std/memory/indirect/ctor.cc > index dfd9341582f..ec34e584b3f 100644 > --- a/libstdc++-v3/testsuite/std/memory/indirect/ctor.cc > +++ b/libstdc++-v3/testsuite/std/memory/indirect/ctor.cc > @@ -16,9 +16,9 @@ > > using __gnu_test::uneq_allocator; > using UneqAlloc = uneq_allocator<int>; > -using ScopedAlloc = std::scoped_allocator_adaptor< > - uneq_allocator<std::vector<int, UneqAlloc>>, > - UneqAlloc>; > +using UneqVecAlloc = uneq_allocator<std::vector<int, UneqAlloc>>; > +using ScopedAlloc > + = std::scoped_allocator_adaptor<UneqVecAlloc, UneqAlloc>; > > struct Obj > { > @@ -61,9 +61,10 @@ test_default_ctor() > if (std::is_constant_evaluated()) > return; > > + const ScopedAlloc scopedAlloc(UneqVecAlloc(11), UneqAlloc(22)); > // Object is constructed using allocator-aware constructor. > std::indirect<std::vector<int, UneqAlloc>, ScopedAlloc> > - i3(std::allocator_arg, ScopedAlloc(11, 22)); > + i3(std::allocator_arg, scopedAlloc); > VERIFY( i3->empty() ); > VERIFY( i3->get_allocator().get_personality() == 22 ); > VERIFY( i3.get_allocator().get_personality() == 11 ); > @@ -99,17 +100,18 @@ test_forwarding_ctor() > if (std::is_constant_evaluated()) > return; > > + const ScopedAlloc scopedAlloc(UneqVecAlloc(11), UneqAlloc(22)); > std::vector<int, UneqAlloc> v{1, 2, 3, 4, 5}; > // Object is constructed using allocator-aware constructor. > std::indirect<std::vector<int, UneqAlloc>, ScopedAlloc> > - i7(std::allocator_arg, ScopedAlloc(11, 22), v); > + i7(std::allocator_arg, scopedAlloc, v); > VERIFY( i7->size() == 5 ); > VERIFY( v.size() == 5 ); > VERIFY( i7->get_allocator().get_personality() == 22 ); > VERIFY( i7.get_allocator().get_personality() == 11 ); > > std::indirect<std::vector<int, UneqAlloc>, ScopedAlloc> > - i8(std::allocator_arg, ScopedAlloc(11, 22), std::move(v)); > + i8(std::allocator_arg, scopedAlloc, std::move(v)); > VERIFY( i8->size() == 5 ); > VERIFY( v.size() == 0 ); > VERIFY( i8->get_allocator().get_personality() == 22 ); > @@ -130,14 +132,16 @@ test_inplace_ctor() > VERIFY( i2->c[1] == 0 ); > > std::indirect<Obj, uneq_allocator<Obj>> > - i3(std::allocator_arg, 42, std::in_place); > + i3(std::allocator_arg, uneq_allocator<Obj>(42), > + std::in_place); > VERIFY( i3->i == 0 ); > VERIFY( i3->c[0] == 0 ); > VERIFY( i3->c[1] == 0 ); > VERIFY( i3.get_allocator().get_personality() == 42 ); > > - std::indirect<Obj, uneq_allocator<Obj>> > - i4(std::allocator_arg, 42, std::in_place, 10); > + std::indirect<Obj, uneq_allocator<Obj>> > + i4(std::allocator_arg, uneq_allocator<Obj>(42), > + std::in_place, 10); > VERIFY( i4->i == 10 ); > VERIFY( i4->c[0] == 0 ); > VERIFY( i4->c[1] == 0 ); > @@ -174,15 +178,16 @@ test_inplace_ctor() > if (std::is_constant_evaluated()) > return; > > + const ScopedAlloc scopedAlloc(UneqVecAlloc(11), UneqAlloc(22)); > std::indirect<std::vector<int, UneqAlloc>, ScopedAlloc> > - i14(std::allocator_arg, ScopedAlloc(11, 22), > + i14(std::allocator_arg, scopedAlloc, > std::in_place); > VERIFY( i14->size() == 0 ); > VERIFY( i14->get_allocator().get_personality() == 22 ); > VERIFY( i14.get_allocator().get_personality() == 11 ); > > std::indirect<std::vector<int, UneqAlloc>, ScopedAlloc> > - i15(std::allocator_arg, ScopedAlloc(11, 22), > + i15(std::allocator_arg, scopedAlloc, > std::in_place, 5, 13); > VERIFY( i15->size() == 5 ); > VERIFY( i15->at(0) == 13 ); > @@ -190,7 +195,7 @@ test_inplace_ctor() > VERIFY( i15.get_allocator().get_personality() == 11 ); > > std::indirect<std::vector<int, UneqAlloc>, ScopedAlloc> > - i16(std::allocator_arg, ScopedAlloc(11, 22), > + i16(std::allocator_arg, scopedAlloc, > std::in_place, {1, 2, 3, 4}); > VERIFY( i16->size() == 4 ); > VERIFY( i16->at(2) == 3 ); > diff --git a/libstdc++-v3/testsuite/std/memory/polymorphic/ctor.cc > b/libstdc++-v3/testsuite/std/memory/polymorphic/ctor.cc > index 4d043db0ea4..a81d5615b4a 100644 > --- a/libstdc++-v3/testsuite/std/memory/polymorphic/ctor.cc > +++ b/libstdc++-v3/testsuite/std/memory/polymorphic/ctor.cc > @@ -16,9 +16,9 @@ > > using __gnu_test::uneq_allocator; > using UneqAlloc = uneq_allocator<int>; > -using ScopedAlloc = std::scoped_allocator_adaptor< > - uneq_allocator<std::vector<int, UneqAlloc>>, > - UneqAlloc>; > +using UneqVecAlloc = uneq_allocator<std::vector<int, UneqAlloc>>; > +using ScopedAlloc > + = std::scoped_allocator_adaptor<UneqVecAlloc, UneqAlloc>; > > struct Obj > { > @@ -48,9 +48,10 @@ test_default_ctor() > if (std::is_constant_evaluated()) > return; > > + const ScopedAlloc scopedAlloc(UneqVecAlloc(11), UneqAlloc(22)); > // Object is constructed using allocator-aware constructor. > std::polymorphic<std::vector<int, UneqAlloc>, ScopedAlloc> > - i3(std::allocator_arg, ScopedAlloc(11, 22)); > + i3(std::allocator_arg, scopedAlloc); > VERIFY( i3->empty() ); > VERIFY( i3->get_allocator().get_personality() == 22 ); > VERIFY( i3.get_allocator().get_personality() == 11 ); > @@ -82,17 +83,18 @@ test_forwarding_ctor() > if (std::is_constant_evaluated()) > return; > > + const ScopedAlloc scopedAlloc(UneqVecAlloc(11), UneqAlloc(22)); > std::vector<int, UneqAlloc> v{1, 2, 3, 4, 5}; > // Object is constructed using allocator-aware constructor. > std::polymorphic<std::vector<int, UneqAlloc>, ScopedAlloc> > - i7(std::allocator_arg, ScopedAlloc(11, 22), v); > + i7(std::allocator_arg, scopedAlloc, v); > VERIFY( i7->size() == 5 ); > VERIFY( v.size() == 5 ); > VERIFY( i7->get_allocator().get_personality() == 22 ); > VERIFY( i7.get_allocator().get_personality() == 11 ); > > std::polymorphic<std::vector<int, UneqAlloc>, ScopedAlloc> > - i8(std::allocator_arg, ScopedAlloc(11, 22), std::move(v)); > + i8(std::allocator_arg, scopedAlloc, std::move(v)); > VERIFY( i8->size() == 5 ); > VERIFY( v.size() == 0 ); > VERIFY( i8->get_allocator().get_personality() == 22 ); > @@ -113,14 +115,16 @@ test_inplace_ctor() > VERIFY( i2->c[1] == 0 ); > > std::polymorphic<Obj, uneq_allocator<Obj>> > - i3(std::allocator_arg, 42, std::in_place_type<Obj>); > + i3(std::allocator_arg, uneq_allocator<Obj>(42), > + std::in_place_type<Obj>); > VERIFY( i3->i == 0 ); > VERIFY( i3->c[0] == 0 ); > VERIFY( i3->c[1] == 0 ); > VERIFY( i3.get_allocator().get_personality() == 42 ); > > std::polymorphic<Obj, uneq_allocator<Obj>> > - i4(std::allocator_arg, 42, std::in_place_type<Obj>, 10); > + i4(std::allocator_arg, uneq_allocator<Obj>(42), > + std::in_place_type<Obj>, 10); > VERIFY( i4->i == 10 ); > VERIFY( i4->c[0] == 0 ); > VERIFY( i4->c[1] == 0 ); > @@ -160,15 +164,16 @@ test_inplace_ctor() > if (std::is_constant_evaluated()) > return; > > + const ScopedAlloc scopedAlloc(UneqVecAlloc(11), UneqAlloc(22)); > std::polymorphic<std::vector<int, UneqAlloc>, ScopedAlloc> > - i14(std::allocator_arg, ScopedAlloc(11, 22), > + i14(std::allocator_arg, scopedAlloc, > std::in_place_type<std::vector<int, UneqAlloc>>); > VERIFY( i14->size() == 0 ); > VERIFY( i14->get_allocator().get_personality() == 22 ); > VERIFY( i14.get_allocator().get_personality() == 11 ); > > std::polymorphic<std::vector<int, UneqAlloc>, ScopedAlloc> > - i15(std::allocator_arg, ScopedAlloc(11, 22), > + i15(std::allocator_arg, scopedAlloc, > std::in_place_type<std::vector<int, UneqAlloc>>, 5, 13); > VERIFY( i15->size() == 5 ); > VERIFY( i15->at(0) == 13 ); > @@ -176,7 +181,7 @@ test_inplace_ctor() > VERIFY( i15.get_allocator().get_personality() == 11 ); > > std::polymorphic<std::vector<int, UneqAlloc>, ScopedAlloc> > - i16(std::allocator_arg, ScopedAlloc(11, 22), > + i16(std::allocator_arg, scopedAlloc, > std::in_place_type<std::vector<int, UneqAlloc>>, {1, 2, 3, 4}); > VERIFY( i16->size() == 4 ); > VERIFY( i16->at(2) == 3 ); > diff --git a/libstdc++-v3/testsuite/std/memory/polymorphic/ctor_poly.cc > b/libstdc++-v3/testsuite/std/memory/polymorphic/ctor_poly.cc > index cb18031a903..2c275d199d9 100644 > --- a/libstdc++-v3/testsuite/std/memory/polymorphic/ctor_poly.cc > +++ b/libstdc++-v3/testsuite/std/memory/polymorphic/ctor_poly.cc > @@ -129,16 +129,17 @@ test_forwarding_ctor() > if (std::is_constant_evaluated()) > return; > > + const ScopedAlloc scopedAlloc(uneq_allocator<Base>(11), UneqAlloc(22)); > const VecDerived<int, UneqAlloc> v{1, 2, 3, 4, 5}; > // Object is constructed using allocator-aware constructor. > std::polymorphic<Base, ScopedAlloc> > - i5(std::allocator_arg, ScopedAlloc(11, 22), v); > + i5(std::allocator_arg, scopedAlloc, v); > VERIFY( *i5 == v ); > VERIFY( i5->get_personality() == 22 ); > VERIFY( i5.get_allocator().get_personality() == 11 ); > > std::polymorphic<Base, ScopedAlloc> > - i6(std::allocator_arg, ScopedAlloc(11, 22), auto(v)); > + i6(std::allocator_arg, scopedAlloc, auto(v)); > VERIFY( *i6 == v ); > VERIFY( i6->get_personality() == 22 ); > VERIFY( i6.get_allocator().get_personality() == 11 ); > @@ -156,13 +157,15 @@ test_inplace_ctor() > VERIFY( i2->get_personality() == -2 ); > > std::polymorphic<Base, uneq_allocator<Base>> > - i3(std::allocator_arg, 42, std::in_place_type<ObjDerived>); > + i3(std::allocator_arg, uneq_allocator<Base>(42), > + std::in_place_type<ObjDerived>); > VERIFY( *i3 == ObjDerived() ); > VERIFY( i3->get_personality() == -2 ); > VERIFY( i3.get_allocator().get_personality() == 42 ); > > std::polymorphic<Base, uneq_allocator<Base>> > - i4(std::allocator_arg, 42, std::in_place_type<ObjDerived>, 10, 20, > 30); > + i4(std::allocator_arg, uneq_allocator<Base>(42), > + std::in_place_type<ObjDerived>, 10, 20, 30); > VERIFY( *i4 == ObjDerived(10, 20, 30) ); > VERIFY( i4->get_personality() == -2 ); > VERIFY( i4.get_allocator().get_personality() == 42 ); > @@ -189,22 +192,23 @@ test_inplace_ctor() > if (std::is_constant_evaluated()) > return; > > + const ScopedAlloc scopedAlloc(uneq_allocator<Base>(11), UneqAlloc(22)); > std::polymorphic<Base, ScopedAlloc> > - i8(std::allocator_arg, ScopedAlloc(11, 22), > + i8(std::allocator_arg, scopedAlloc, > std::in_place_type<VecDerived<int, UneqAlloc>>); > VERIFY( *i8 == ze ); > VERIFY( i8->get_personality() == 22 ); > VERIFY( i8.get_allocator().get_personality() == 11 ); > > std::polymorphic<Base, ScopedAlloc> > - i9(std::allocator_arg, ScopedAlloc(11, 22), > + i9(std::allocator_arg, scopedAlloc, > std::in_place_type<VecDerived<int, UneqAlloc>>, 5, 13); > VERIFY( *i9 == fe ); > VERIFY( i9->get_personality() == 22 ); > VERIFY( i9.get_allocator().get_personality() == 11 ); > > std::polymorphic<Base, ScopedAlloc> > - i10(std::allocator_arg, ScopedAlloc(11, 22), > + i10(std::allocator_arg, scopedAlloc, > std::in_place_type<VecDerived<int, UneqAlloc>>, {1, 2, 3, 4}); > VERIFY( *i10 == il ); > VERIFY( i10->get_personality() == 22 ); > diff --git a/libstdc++-v3/testsuite/util/testsuite_allocator.h > b/libstdc++-v3/testsuite/util/testsuite_allocator.h > index 295b458e3c6..892a385e307 100644 > --- a/libstdc++-v3/testsuite/util/testsuite_allocator.h > +++ b/libstdc++-v3/testsuite/util/testsuite_allocator.h > @@ -332,7 +332,7 @@ namespace __gnu_test > uneq_allocator() _GLIBCXX_USE_NOEXCEPT > : personality(0) { } > > - _GLIBCXX_CONSTEXPR > + _GLIBCXX_CONSTEXPR explicit > uneq_allocator(int person) _GLIBCXX_USE_NOEXCEPT > : personality(person) { } > > -- > 2.53.0 > >
