On Thu, 12 Feb 2026, 22:00 Tomasz Kamiński, <[email protected]> wrote:
> Presence implicit conversion from int to it's allocator, makes the
> following
> makes constructing
There seem to be some extra words here, "makes the following makes
constructing"
string from rvalue of same string type and int ambigous,
> 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.
>
Users can still have the same problems with their own allocators, but
they're not our fault, and there nothing we can do about that.
OK with the wording cleaned up above.
> 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.
> ---
> Tested on x86_64-linux. OK for 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
>
>