blob: dfd9341582f5706292d4e8e35d77aacebcb5b7c5 [file] [log] [blame]
// { dg-do run { target c++26 } }
#include <memory>
#include <scoped_allocator>
#include <utility>
#include <vector>
#ifndef __cpp_lib_indirect
# error __cpp_lib_indirect feature test macro missing in <memory>
#elif __cpp_lib_indirect != 202502
# error __cpp_lib_indirect feature test macro has wrong value in <memory>
#endif
#include <testsuite_hooks.h>
#include <testsuite_allocator.h>
using __gnu_test::uneq_allocator;
using UneqAlloc = uneq_allocator<int>;
using ScopedAlloc = std::scoped_allocator_adaptor<
uneq_allocator<std::vector<int, UneqAlloc>>,
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<decltype(i1), std::indirect<Obj>>);
using Alloc = __gnu_test::SimpleAllocator<Obj>;
Alloc a;
std::indirect i2(std::allocator_arg, a, o);
static_assert(std::is_same_v<decltype(i2), std::indirect<Obj, Alloc>>);
}
constexpr void
test_default_ctor()
{
using __gnu_test::default_init_allocator;
std::indirect<Obj, default_init_allocator<Obj>> i1;
default_init_allocator<int> 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<Obj, default_init_allocator<Obj>> 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<std::vector<int, UneqAlloc>, 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<Obj> const& i)
{
VERIFY( i->i == 1 );
VERIFY( i->c[0] == '2' );
VERIFY( i->c[1] == '3' );
};
std::indirect<Obj> i1(std::as_const(obj));
verify(i1);
std::indirect<Obj> i2(std::move(std::as_const(obj)));
verify(i2);
std::indirect<Obj> i3(obj);
verify(i3);
std::indirect<Obj> i4(std::move(obj));
verify(i4);
std::indirect<Obj> i5({1, {'2', '3'}});
verify(i5);
// Aggregate parens init
std::indirect<Obj> i6(7);
VERIFY( i6->i == 7 );
if (std::is_constant_evaluated())
return;
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);
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));
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<Obj> i1(std::in_place);
VERIFY( i1->i == 0 );
VERIFY( i1->c[0] == 0 );
VERIFY( i1->c[1] == 0 );
std::indirect<Obj> i2(std::in_place, 10);
VERIFY( i2->i == 10 );
VERIFY( i2->c[0] == 0 );
VERIFY( i2->c[1] == 0 );
std::indirect<Obj, uneq_allocator<Obj>>
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<Obj, uneq_allocator<Obj>>
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<std::vector<int>> i5(std::in_place);
VERIFY( i5->size() == 0 );
std::indirect<std::vector<int>> i6(std::in_place, 5, 13);
VERIFY( i6->size() == 5 );
VERIFY( i6->at(0) == 13 );
std::indirect<std::vector<int>> i7(std::in_place, {1, 2, 3, 4});
VERIFY( i7->size() == 4 );
VERIFY( i7->at(2) == 3 );
std::indirect<std::vector<int, UneqAlloc>>
i8(std::in_place, UneqAlloc{42});
VERIFY( i8->size() == 0 );
VERIFY( i8->get_allocator().get_personality() == 42 );
std::indirect<std::vector<int, UneqAlloc>>
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<std::vector<int, UneqAlloc>>
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<std::vector<int, UneqAlloc>, 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<std::vector<int, UneqAlloc>, 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<std::vector<int, UneqAlloc>, 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;
}());
}