// { dg-do run { target c++26 } } #include #include #include #include #include #include struct Base { friend constexpr bool operator==(const Base& lhs, const Base& rhs) { return lhs.eq(rhs); } private: constexpr virtual bool eq(const Base& other) const = 0; }; struct Derived : Base { constexpr Derived() : x(0), y(0), z(0) { } constexpr Derived(int a, int b, int c) : x(a), y(b), z(c) { } private: constexpr bool eq(const Base& other) const override { if (auto op = dynamic_cast(&other)) return this->x == op->x && this->y == op->y && this->z == op->z; return false; } int x; int y; int z; }; using __gnu_test::tracker_allocator; using Counter = __gnu_test::tracker_allocator_counter; using Polymorphic = std::polymorphic>; const Polymorphic src(std::in_place_type, 1, 2, 3); void test_ctor() { Counter::reset(); Polymorphic i1(src); VERIFY( *i1 == *src ); VERIFY( &*i1 != &*src ); VERIFY( Counter::get_allocation_count() >= sizeof(Derived) ); 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, {}, src); VERIFY( *i2 == *src ); VERIFY( &*i2 != &*src ); VERIFY( Counter::get_allocation_count() >= sizeof(Derived) ); VERIFY( Counter::get_deallocation_count() == 0 ); VERIFY( Counter::get_construct_count() == 2 ); VERIFY( Counter::get_destruct_count() == 0 ); } void test_assign() { Counter::reset(); Polymorphic i1(std::in_place_type); const size_t holderSize = Counter::get_allocation_count(); VERIFY( holderSize >= sizeof(Derived) ); Counter::reset(); i1 = src; VERIFY( *i1 == *src ); VERIFY( &*i1 != &*src ); VERIFY( Counter::get_allocation_count() == holderSize ); VERIFY( Counter::get_deallocation_count() == holderSize ); VERIFY( Counter::get_construct_count() == 2 ); VERIFY( Counter::get_destruct_count() == 1 ); auto(std::move(i1)); Counter::reset(); i1 = src; VERIFY( *i1 == *src ); VERIFY( &*i1 != &*src ); VERIFY( Counter::get_allocation_count() == holderSize ); VERIFY( Counter::get_deallocation_count() == 0 ); VERIFY( Counter::get_construct_count() == 2 ); VERIFY( Counter::get_destruct_count() == 0 ); } void test_valueless() { Polymorphic e(std::in_place_type); auto(std::move(e)); VERIFY( e.valueless_after_move() ); Counter::reset(); Polymorphic i1(e); VERIFY( i1.valueless_after_move() ); 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 i2(std::allocator_arg, {}, e); VERIFY( i2.valueless_after_move() ); 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(src); Counter::reset(); i3 = e; VERIFY( i3.valueless_after_move() ); VERIFY( Counter::get_allocation_count() == 0 ); VERIFY( Counter::get_deallocation_count() >= sizeof(Derived) ); VERIFY( Counter::get_construct_count() == 0 ); VERIFY( Counter::get_destruct_count() == 1 ); Counter::reset(); i3 = e; VERIFY( i3.valueless_after_move() ); VERIFY( Counter::get_allocation_count() == 0 ); VERIFY( Counter::get_deallocation_count() == 0 ); VERIFY( Counter::get_construct_count() == 0 ); VERIFY( Counter::get_destruct_count() == 0 ); } constexpr void test_constexpr() { using Polymorphic = std::polymorphic>; const Polymorphic src(std::in_place_type, 1, 2, 3); Polymorphic i1(src); VERIFY( *i1 == *src ); VERIFY( &*i1 != &*src ); Polymorphic i2(std::allocator_arg, {}, src); VERIFY( *i2 == *src ); VERIFY( &*i2 != &*src ); i1 = Polymorphic(std::in_place_type); VERIFY( *i1 != *src ); i1 = src; VERIFY( *i1 == *src ); VERIFY( &*i1 != &*src ); auto(std::move(i1)); i1 = src; VERIFY( *i1 == *src ); VERIFY( &*i1 != &*src ); Polymorphic e(std::in_place_type); auto(std::move(e)); VERIFY( e.valueless_after_move() ); Polymorphic e1(e); VERIFY( e1.valueless_after_move() ); Polymorphic e2(std::allocator_arg, {}, e); VERIFY( e2.valueless_after_move() ); Polymorphic e3(src); e3 = e; VERIFY( e3.valueless_after_move() ); } int main() { test_ctor(); test_assign(); test_valueless(); test_constexpr(); static_assert([] { test_constexpr(); return true; }()); }