// { dg-do run { target c++26 } } #include #include #include #include #ifndef __cpp_lib_indirect # error __cpp_lib_indirect feature test macro missing in #elif __cpp_lib_indirect != 202502 # error __cpp_lib_indirect feature test macro has wrong value in #endif #include #include using __gnu_test::uneq_allocator; using UneqAlloc = uneq_allocator; using ScopedAlloc = std::scoped_allocator_adaptor< uneq_allocator>, UneqAlloc>; struct Obj { int i; char c[2]; }; constexpr void test_deduction_guides() { const Obj o{}; std::indirect i1(o); static_assert(std::is_same_v>); using Alloc = __gnu_test::SimpleAllocator; Alloc a; std::indirect i2(std::allocator_arg, a, o); static_assert(std::is_same_v>); } constexpr void test_default_ctor() { using __gnu_test::default_init_allocator; std::indirect> i1; default_init_allocator a{}; // The contained object and the allocator should be value-initialized. VERIFY( i1->i == 0 ); VERIFY( i1->c[0] == 0 ); VERIFY( i1->c[1] == 0 ); VERIFY( i1.get_allocator() == a ); a.state = 5; // Allocator-extended default constructor: std::indirect> i2(std::allocator_arg, a); VERIFY( i2.get_allocator() == a ); if (std::is_constant_evaluated()) return; // Object is constructed using allocator-aware constructor. std::indirect, ScopedAlloc> i3(std::allocator_arg, ScopedAlloc(11, 22)); VERIFY( i3->empty() ); VERIFY( i3->get_allocator().get_personality() == 22 ); VERIFY( i3.get_allocator().get_personality() == 11 ); } constexpr void test_forwarding_ctor() { Obj obj{1, {'2', '3'}}; auto verify = [](std::indirect const& i) { VERIFY( i->i == 1 ); VERIFY( i->c[0] == '2' ); VERIFY( i->c[1] == '3' ); }; std::indirect i1(std::as_const(obj)); verify(i1); std::indirect i2(std::move(std::as_const(obj))); verify(i2); std::indirect i3(obj); verify(i3); std::indirect i4(std::move(obj)); verify(i4); std::indirect i5({1, {'2', '3'}}); verify(i5); // Aggregate parens init std::indirect i6(7); VERIFY( i6->i == 7 ); if (std::is_constant_evaluated()) return; std::vector v{1, 2, 3, 4, 5}; // Object is constructed using allocator-aware constructor. std::indirect, ScopedAlloc> i7(std::allocator_arg, ScopedAlloc(11, 22), 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, ScopedAlloc> i8(std::allocator_arg, ScopedAlloc(11, 22), std::move(v)); VERIFY( i8->size() == 5 ); VERIFY( v.size() == 0 ); VERIFY( i8->get_allocator().get_personality() == 22 ); VERIFY( i8.get_allocator().get_personality() == 11 ); } constexpr void test_inplace_ctor() { std::indirect i1(std::in_place); VERIFY( i1->i == 0 ); VERIFY( i1->c[0] == 0 ); VERIFY( i1->c[1] == 0 ); std::indirect i2(std::in_place, 10); VERIFY( i2->i == 10 ); VERIFY( i2->c[0] == 0 ); VERIFY( i2->c[1] == 0 ); std::indirect> i3(std::allocator_arg, 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> i4(std::allocator_arg, 42, std::in_place, 10); VERIFY( i4->i == 10 ); VERIFY( i4->c[0] == 0 ); VERIFY( i4->c[1] == 0 ); VERIFY( i4.get_allocator().get_personality() == 42 ); std::indirect> i5(std::in_place); VERIFY( i5->size() == 0 ); std::indirect> i6(std::in_place, 5, 13); VERIFY( i6->size() == 5 ); VERIFY( i6->at(0) == 13 ); std::indirect> i7(std::in_place, {1, 2, 3, 4}); VERIFY( i7->size() == 4 ); VERIFY( i7->at(2) == 3 ); std::indirect> i8(std::in_place, UneqAlloc{42}); VERIFY( i8->size() == 0 ); VERIFY( i8->get_allocator().get_personality() == 42 ); std::indirect> i9(std::in_place, 5, 13, UneqAlloc{42}); VERIFY( i9->size() == 5 ); VERIFY( i9->at(0) == 13 ); VERIFY( i9->get_allocator().get_personality() == 42 ); std::indirect> i10(std::in_place, {1, 2, 3, 4}, UneqAlloc{42}); VERIFY( i10->size() == 4 ); VERIFY( i10->at(2) == 3 ); VERIFY( i10->get_allocator().get_personality() == 42 ); if (std::is_constant_evaluated()) return; std::indirect, ScopedAlloc> i14(std::allocator_arg, ScopedAlloc(11, 22), std::in_place); VERIFY( i14->size() == 0 ); VERIFY( i14->get_allocator().get_personality() == 22 ); VERIFY( i14.get_allocator().get_personality() == 11 ); std::indirect, ScopedAlloc> i15(std::allocator_arg, ScopedAlloc(11, 22), std::in_place, 5, 13); VERIFY( i15->size() == 5 ); VERIFY( i15->at(0) == 13 ); VERIFY( i15->get_allocator().get_personality() == 22 ); VERIFY( i15.get_allocator().get_personality() == 11 ); std::indirect, ScopedAlloc> i16(std::allocator_arg, ScopedAlloc(11, 22), std::in_place, {1, 2, 3, 4}); VERIFY( i16->size() == 4 ); VERIFY( i16->at(2) == 3 ); VERIFY( i16->get_allocator().get_personality() == 22 ); VERIFY( i16.get_allocator().get_personality() == 11 ); } int main() { test_default_ctor(); test_forwarding_ctor(); test_inplace_ctor(); static_assert([] { test_default_ctor(); test_forwarding_ctor(); test_inplace_ctor(); return true; }()); }