// { dg-do run { target c++26 } } #include #include #include #include #include #include struct Base { friend bool operator==(const Base& lhs, const Base& rhs) { return lhs.eq(rhs); } virtual int get_alloc_personality() const { return -1; } private: virtual bool eq(const Base& other) const = 0; }; template struct VecDerived : Base, std::vector { using VecBase = std::vector; using VecBase::VecBase; int get_alloc_personality() const override { return this->get_allocator().get_personality(); } private: bool eq(const Base& other) const override { if (auto op = dynamic_cast(&other)) return *static_cast(this) == *static_cast(op); return false; } }; using __gnu_test::propagating_allocator; using __gnu_test::tracker_allocator; using Counter = __gnu_test::tracker_allocator_counter; template void test_ctor() { using PropAlloc = propagating_allocator; using Vector = VecDerived; using ScopedAlloc = std::scoped_allocator_adaptor< propagating_allocator>, PropAlloc>; using Polymorphic = std::polymorphic; const Polymorphic src(std::allocator_arg, ScopedAlloc{11, 22}, std::in_place_type, {1, 2, 3}); Counter::reset(); Polymorphic i1(src); VERIFY( *i1 == *src ); VERIFY( &*i1 != &*src ); if (Propagate) { VERIFY( i1->get_alloc_personality() == 22 ); VERIFY( i1.get_allocator().get_personality() == 11 ); } else { VERIFY( i1->get_alloc_personality() == 0 ); VERIFY( i1.get_allocator().get_personality() == 0 ); } VERIFY( Counter::get_allocation_count() >= sizeof(Vector) ); VERIFY( Counter::get_deallocation_count() == 0 ); VERIFY( Counter::get_construct_count() == 2 ); VERIFY( Counter::get_destruct_count() == 0 ); Counter::reset(); Polymorphic i2(std::allocator_arg, ScopedAlloc{33, 44}, src); VERIFY( *i2 == *src ); VERIFY( &*i2 != &*src ); VERIFY( i2->get_alloc_personality() == 44 ); VERIFY( i2.get_allocator().get_personality() == 33 ); VERIFY( Counter::get_allocation_count() >= sizeof(Vector) ); VERIFY( Counter::get_deallocation_count() == 0 ); VERIFY( Counter::get_construct_count() == 2 ); VERIFY( Counter::get_destruct_count() == 0 ); } template void test_assign() { using PropAlloc = propagating_allocator; using Vector = VecDerived; using ScopedAlloc = std::scoped_allocator_adaptor< propagating_allocator>, PropAlloc>; using Polymorphic = std::polymorphic; const Polymorphic src(std::allocator_arg, ScopedAlloc{11, 22}, std::in_place_type, {1, 2, 3}); Counter::reset(); Polymorphic i1(std::allocator_arg, ScopedAlloc{11, 22}, std::in_place_type); const size_t holderSize = Counter::get_allocation_count(); VERIFY( holderSize >= sizeof(Vector) ); Counter::reset(); i1 = src; VERIFY( *i1 == *src ); VERIFY( &*i1 != &*src ); VERIFY( i1->get_alloc_personality() == 22 ); VERIFY( i1.get_allocator().get_personality() == 11 ); VERIFY( Counter::get_allocation_count() == holderSize ); VERIFY( Counter::get_deallocation_count() == holderSize ); VERIFY( Counter::get_construct_count() == 2 ); VERIFY( Counter::get_destruct_count() == 1 ); Polymorphic i2(std::allocator_arg, ScopedAlloc{33, 44}); Counter::reset(); i2 = src; VERIFY( *i2 == *src ); VERIFY( &*i2 != &*src ); if (Propagate) { VERIFY( i2->get_alloc_personality() == 22 ); VERIFY( i2.get_allocator().get_personality() == 11 ); } else { VERIFY( i2->get_alloc_personality() == 44 ); VERIFY( i2.get_allocator().get_personality() == 33 ); } VERIFY( Counter::get_allocation_count() == holderSize ); VERIFY( Counter::get_deallocation_count() == holderSize ); VERIFY( Counter::get_construct_count() == 2 ); VERIFY( Counter::get_destruct_count() == 1 ); Polymorphic i3(std::allocator_arg, ScopedAlloc{11, 22}); auto(std::move(i3)); Counter::reset(); i3 = src; VERIFY( *i3 == *src ); VERIFY( &*i3 != &*src ); VERIFY( i3->get_alloc_personality() == 22 ); VERIFY( i3.get_allocator().get_personality() == 11 ); VERIFY( Counter::get_allocation_count() == holderSize ); VERIFY( Counter::get_deallocation_count() == 0 ); VERIFY( Counter::get_construct_count() == 2 ); VERIFY( Counter::get_destruct_count() == 0 ); Polymorphic i4(std::allocator_arg, ScopedAlloc{33, 44}); auto(std::move(i4)); Counter::reset(); i4 = src; VERIFY( *i4 == *src ); VERIFY( &*i4 != &*src ); if (Propagate) { VERIFY( i4->get_alloc_personality() == 22 ); VERIFY( i4.get_allocator().get_personality() == 11 ); } else { VERIFY( i4->get_alloc_personality() == 44 ); VERIFY( i4.get_allocator().get_personality() == 33 ); } VERIFY( Counter::get_allocation_count() == holderSize ); VERIFY( Counter::get_deallocation_count() == 0 ); VERIFY( Counter::get_construct_count() == 2 ); VERIFY( Counter::get_destruct_count() == 0 ); } template void test_valueless() { using PropAlloc = propagating_allocator; using Vector = VecDerived; using ScopedAlloc = std::scoped_allocator_adaptor< propagating_allocator>, PropAlloc>; using Polymorphic = std::polymorphic; Polymorphic e(std::allocator_arg, ScopedAlloc{11, 22}, std::in_place_type); auto(std::move(e)); VERIFY( e.valueless_after_move() ); Counter::reset(); Polymorphic i1(e); VERIFY( i1.valueless_after_move() ); if (Propagate) VERIFY( i1.get_allocator().get_personality() == 11 ); else VERIFY( i1.get_allocator().get_personality() == 0 ); VERIFY( Counter::get_allocation_count() == 0 ); VERIFY( Counter::get_deallocation_count() == 0 ); VERIFY( Counter::get_construct_count() == 0 ); VERIFY( Counter::get_destruct_count() == 0 ); Counter::reset(); Polymorphic i2(std::allocator_arg, ScopedAlloc{33, 44}, e); VERIFY( i2.valueless_after_move() ); VERIFY( i2.get_allocator().get_personality() == 33 ); VERIFY( Counter::get_allocation_count() == 0 ); VERIFY( Counter::get_deallocation_count() == 0 ); VERIFY( Counter::get_construct_count() == 0 ); VERIFY( Counter::get_destruct_count() == 0 ); Polymorphic i3(std::allocator_arg, ScopedAlloc{33, 44}); Counter::reset(); i3 = e; VERIFY( i3.valueless_after_move() ); if (Propagate) VERIFY( i3.get_allocator().get_personality() == 11 ); else VERIFY( i3.get_allocator().get_personality() == 33 ); VERIFY( Counter::get_allocation_count() == 0 ); VERIFY( Counter::get_deallocation_count() >= sizeof(Vector) ); VERIFY( Counter::get_construct_count() == 0 ); VERIFY( Counter::get_destruct_count() == 1 ); Counter::reset(); i2 = e; VERIFY( i2.valueless_after_move() ); if (Propagate) VERIFY( i2.get_allocator().get_personality() == 11 ); else VERIFY( i2.get_allocator().get_personality() == 33 ); VERIFY( Counter::get_allocation_count() == 0 ); VERIFY( Counter::get_deallocation_count() == 0 ); VERIFY( Counter::get_construct_count() == 0 ); VERIFY( Counter::get_destruct_count() == 0 ); } template void test_all() { test_ctor(); test_assign(); test_valueless(); } int main() { test_all(); test_all(); }