| // Copyright (C) 2019-2021 Free Software Foundation, Inc. |
| // |
| // This file is part of the GNU ISO C++ Library. This library is free |
| // software; you can redistribute it and/or modify it under the |
| // terms of the GNU General Public License as published by the |
| // Free Software Foundation; either version 3, or (at your option) |
| // any later version. |
| |
| // This library is distributed in the hope that it will be useful, |
| // but WITHOUT ANY WARRANTY; without even the implied warranty of |
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| // GNU General Public License for more details. |
| |
| // You should have received a copy of the GNU General Public License along |
| // with this library; see the file COPYING3. If not see |
| // <http://www.gnu.org/licenses/>. |
| |
| // { dg-options "-std=gnu++2a" } |
| // { dg-do run { target c++2a } } |
| |
| #include <testsuite_hooks.h> |
| #include <testsuite_allocator.h> |
| |
| using test_allocator = __gnu_test::uneq_allocator<int>; |
| |
| struct Arg { }; |
| |
| struct A |
| { |
| A() : nargs(0) { } |
| A(float&) : nargs(1) { } |
| A(int, void*) : nargs(2) { } |
| |
| // These should not be used: |
| A(const test_allocator& a); |
| A(float&, const test_allocator& a); |
| A(int, void*, const test_allocator& a); |
| |
| const int nargs; |
| const int alloc_id = -1; |
| |
| // std::uses_allocator<A, test_allocator> should be false: |
| using allocator_type = void*(); |
| }; |
| |
| struct B |
| { |
| // This means std::uses_allocator<B, test_allocator> is true: |
| using allocator_type = test_allocator; |
| |
| B() : nargs(0) { } |
| B(float&) : nargs(1) { } |
| B(int, void*) : nargs(2) { } |
| |
| B(std::allocator_arg_t, const test_allocator& a) |
| : nargs(0), alloc_id(a.get_personality()) { } |
| B(std::allocator_arg_t, const test_allocator& a, float&) |
| : nargs(1), alloc_id(a.get_personality()) { } |
| B(std::allocator_arg_t, const test_allocator& a, int, void*) |
| : nargs(2), alloc_id(a.get_personality()) { } |
| B(std::allocator_arg_t, const test_allocator& a, B&& b) |
| : nargs(b.nargs), alloc_id(a.get_personality()) { } |
| |
| // These should not be used: |
| B(const test_allocator&); |
| B(float&, const test_allocator&, float&); |
| B(int, void*, const test_allocator&); |
| B(const test_allocator&, float&); |
| B(const test_allocator&, int, void*); |
| B(B&&); |
| B(B&&, const test_allocator&); |
| |
| const int nargs; |
| const int alloc_id = -1; |
| }; |
| |
| struct C |
| { |
| C() : nargs(0) { } |
| C(float&) : nargs(1) { } |
| C(int, void*) : nargs(2) { } |
| |
| C(const test_allocator& a) |
| : nargs(0), alloc_id(a.get_personality()) { } |
| C(float&, const test_allocator& a) |
| : nargs(1), alloc_id(a.get_personality()) { } |
| C(int, void*, const test_allocator& a) |
| : nargs(2), alloc_id(a.get_personality()) { } |
| C(C&& c, const test_allocator& a) |
| : nargs(c.nargs), alloc_id(a.get_personality()) { } |
| |
| C(C&&); |
| |
| const int nargs; |
| const int alloc_id = -1; |
| }; |
| |
| namespace std { |
| // This means std::uses_allocator<C, test_allocator> is true: |
| template<> struct uses_allocator<C, test_allocator> : std::true_type { }; |
| } |
| |
| test_allocator alloc1(1); |
| test_allocator alloc2(2); |
| |
| void |
| test01() |
| { |
| auto i0 = std::make_obj_using_allocator<int>(alloc1, 2); |
| VERIFY( i0 == 2 ); |
| |
| float f = 0.0f; |
| |
| auto a0 = std::make_obj_using_allocator<A>(alloc1); |
| VERIFY( a0.nargs == 0 ); |
| VERIFY( a0.alloc_id == -1 ); |
| auto a1 = std::make_obj_using_allocator<A>(alloc1, f); |
| VERIFY( a1.nargs == 1 ); |
| VERIFY( a1.alloc_id == -1 ); |
| auto a2 = std::make_obj_using_allocator<A>(alloc1, 123, nullptr); |
| VERIFY( a2.nargs == 2 ); |
| VERIFY( a2.alloc_id == -1 ); |
| |
| auto b0 = std::make_obj_using_allocator<B>(alloc1); |
| VERIFY( b0.nargs == 0 ); |
| VERIFY( b0.alloc_id == 1 ); |
| auto b1 = std::make_obj_using_allocator<B>(alloc2, f); |
| VERIFY( b1.nargs == 1 ); |
| VERIFY( b1.alloc_id == 2 ); |
| auto b2 = std::make_obj_using_allocator<B>(alloc1, 123, nullptr); |
| VERIFY( b2.nargs == 2 ); |
| VERIFY( b2.alloc_id == 1 ); |
| |
| auto c0 = std::make_obj_using_allocator<C>(alloc1); |
| VERIFY( c0.nargs == 0 ); |
| VERIFY( c0.alloc_id == 1 ); |
| auto c1 = std::make_obj_using_allocator<C>(alloc2, f); |
| VERIFY( c1.nargs == 1 ); |
| VERIFY( c1.alloc_id == 2 ); |
| auto c2 = std::make_obj_using_allocator<C>(alloc1, 123, nullptr); |
| VERIFY( c2.nargs == 2 ); |
| VERIFY( c2.alloc_id == 1 ); |
| } |
| |
| void |
| test02() |
| { |
| decltype(auto) b |
| = std::make_obj_using_allocator<const B>(alloc1, 123, nullptr); |
| static_assert( std::is_const_v<decltype(b)> ); |
| VERIFY( b.nargs == 2 ); |
| VERIFY( b.alloc_id == 1 ); |
| |
| decltype(auto) c = std::make_obj_using_allocator<const C>(alloc1); |
| static_assert( std::is_const_v<decltype(c)> ); |
| VERIFY( c.nargs == 0 ); |
| VERIFY( c.alloc_id == 1 ); |
| } |
| |
| void |
| test03() |
| { |
| B b; |
| decltype(auto) ref = std::make_obj_using_allocator<B&>(alloc1, b); |
| static_assert( std::is_same_v<decltype(ref), B&> ); |
| VERIFY( &ref == &b ); |
| VERIFY( ref.nargs == 0 ); |
| VERIFY( ref.alloc_id == -1 ); |
| const B& cref = std::make_obj_using_allocator<const B&>(alloc1, b); |
| static_assert( std::is_same_v<decltype(cref), const B&> ); |
| VERIFY( &cref == &b ); |
| VERIFY( cref.nargs == 0 ); |
| VERIFY( cref.alloc_id == -1 ); |
| } |
| |
| void |
| test04() |
| { |
| struct D |
| { |
| D(std::allocator_arg_t) { } |
| D(std::allocator_arg_t, int) { } |
| |
| // These should not be used: |
| D(std::allocator_arg_t, const test_allocator&); |
| D(std::allocator_arg_t, const test_allocator&, int); |
| |
| ~D() { } |
| }; |
| |
| D d1 = std::make_obj_using_allocator<D>(alloc1, std::allocator_arg); |
| |
| struct E |
| { |
| using allocator_type = test_allocator; |
| |
| E(std::allocator_arg_t, const test_allocator&) { } |
| E(std::allocator_arg_t, int, const test_allocator&) { } |
| |
| // These should not be used: |
| E(std::allocator_arg_t); |
| E(std::allocator_arg_t, int); |
| |
| ~E() { } |
| }; |
| |
| E e1 = std::make_obj_using_allocator<E>(alloc1, std::allocator_arg); |
| E e2 = std::make_obj_using_allocator<E>(alloc2, std::allocator_arg, 2); |
| } |
| |
| void |
| test05() |
| { |
| using std::pair; |
| std::piecewise_construct_t p; |
| std::tuple<> t0; |
| float f = 0.0f; |
| std::tuple<float&> t1(f); |
| std::tuple<int, void*> t2{}; |
| |
| auto aa00 = std::make_obj_using_allocator<pair<A, A>>(alloc1, p, t0, t0); |
| VERIFY( aa00.first.nargs == 0 ); |
| VERIFY( aa00.first.alloc_id == -1 ); |
| VERIFY( aa00.second.nargs == 0 ); |
| VERIFY( aa00.second.alloc_id == -1 ); |
| auto ab00 = std::make_obj_using_allocator<pair<A, B>>(alloc1, p, t0, t0); |
| VERIFY( ab00.first.nargs == 0 ); |
| VERIFY( ab00.first.alloc_id == -1 ); |
| VERIFY( ab00.second.nargs == 0 ); |
| VERIFY( ab00.second.alloc_id == 1 ); |
| auto bc00 = std::make_obj_using_allocator<pair<B, C>>(alloc2, p, t0, t0); |
| VERIFY( bc00.first.nargs == 0 ); |
| VERIFY( bc00.first.alloc_id == 2 ); |
| VERIFY( bc00.second.nargs == 0 ); |
| VERIFY( bc00.second.alloc_id == 2 ); |
| auto cb00 = std::make_obj_using_allocator<pair<C, B>>(alloc2, p, t0, t0); |
| VERIFY( cb00.first.nargs == 0 ); |
| VERIFY( cb00.first.alloc_id == 2 ); |
| VERIFY( cb00.second.nargs == 0 ); |
| VERIFY( cb00.second.alloc_id == 2 ); |
| auto cc00 |
| = std::make_obj_using_allocator<pair<C, const C>>(alloc1, p, t0, t0); |
| VERIFY( cc00.first.nargs == 0 ); |
| VERIFY( cc00.first.alloc_id == 1 ); |
| VERIFY( cc00.second.nargs == 0 ); |
| VERIFY( cc00.second.alloc_id == 1 ); |
| |
| auto aa21 = std::make_obj_using_allocator<pair<A, A>>(alloc1, p, t2, t1); |
| VERIFY( aa21.first.nargs == 2 ); |
| VERIFY( aa21.first.alloc_id == -1 ); |
| VERIFY( aa21.second.nargs == 1 ); |
| VERIFY( aa21.second.alloc_id == -1 ); |
| auto ab21 = std::make_obj_using_allocator<pair<A, B>>(alloc1, p, t2, t1); |
| VERIFY( ab21.first.nargs == 2 ); |
| VERIFY( ab21.first.alloc_id == -1 ); |
| VERIFY( ab21.second.nargs == 1 ); |
| VERIFY( ab21.second.alloc_id == 1 ); |
| auto bc11 = std::make_obj_using_allocator<pair<B, C>>(alloc2, p, t1, t1); |
| VERIFY( bc11.first.nargs == 1 ); |
| VERIFY( bc11.first.alloc_id == 2 ); |
| VERIFY( bc11.second.nargs == 1 ); |
| VERIFY( bc11.second.alloc_id == 2 ); |
| auto cb12 = std::make_obj_using_allocator<pair<C, B>>(alloc2, p, t1, t2); |
| VERIFY( cb12.first.nargs == 1 ); |
| VERIFY( cb12.first.alloc_id == 2 ); |
| VERIFY( cb12.second.nargs == 2 ); |
| VERIFY( cb12.second.alloc_id == 2 ); |
| auto cc22 |
| = std::make_obj_using_allocator<pair<C, const C>>(alloc1, p, t2, t1); |
| VERIFY( cc22.first.nargs == 2 ); |
| VERIFY( cc22.first.alloc_id == 1 ); |
| VERIFY( cc22.second.nargs == 1 ); |
| VERIFY( cc22.second.alloc_id == 1 ); |
| } |
| |
| void |
| test06() |
| { |
| using std::pair; |
| float f = 0.0f; |
| |
| auto aa00 = std::make_obj_using_allocator<pair<A, A>>(alloc1); |
| VERIFY( aa00.first.nargs == 0 ); |
| VERIFY( aa00.first.alloc_id == -1 ); |
| VERIFY( aa00.second.nargs == 0 ); |
| VERIFY( aa00.second.alloc_id == -1 ); |
| auto ab00 = std::make_obj_using_allocator<pair<A, B>>(alloc1); |
| VERIFY( ab00.first.nargs == 0 ); |
| VERIFY( ab00.first.alloc_id == -1 ); |
| VERIFY( ab00.second.nargs == 0 ); |
| VERIFY( ab00.second.alloc_id == 1 ); |
| auto bc00 = std::make_obj_using_allocator<pair<B, C>>(alloc2); |
| VERIFY( bc00.first.nargs == 0 ); |
| VERIFY( bc00.first.alloc_id == 2 ); |
| VERIFY( bc00.second.nargs == 0 ); |
| VERIFY( bc00.second.alloc_id == 2 ); |
| auto cb00 = std::make_obj_using_allocator<pair<C, B>>(alloc2); |
| VERIFY( cb00.first.nargs == 0 ); |
| VERIFY( cb00.first.alloc_id == 2 ); |
| VERIFY( cb00.second.nargs == 0 ); |
| VERIFY( cb00.second.alloc_id == 2 ); |
| auto cc00 = std::make_obj_using_allocator<pair<C, const C>>(alloc1); |
| VERIFY( cc00.first.nargs == 0 ); |
| VERIFY( cc00.first.alloc_id == 1 ); |
| VERIFY( cc00.second.nargs == 0 ); |
| VERIFY( cc00.second.alloc_id == 1 ); |
| |
| auto aa11 = std::make_obj_using_allocator<pair<A, A>>(alloc1, f, f); |
| VERIFY( aa11.first.nargs == 1 ); |
| VERIFY( aa11.first.alloc_id == -1 ); |
| VERIFY( aa11.second.nargs == 1 ); |
| VERIFY( aa11.second.alloc_id == -1 ); |
| auto aba1 = std::make_obj_using_allocator<pair<A, B>>(alloc1, A{}, f); |
| VERIFY( aba1.first.nargs == 0 ); |
| VERIFY( aba1.first.alloc_id == -1 ); |
| VERIFY( aba1.second.nargs == 1 ); |
| VERIFY( aba1.second.alloc_id == 1 ); |
| auto bc11 = std::make_obj_using_allocator<pair<B, C>>(alloc2, f, f); |
| VERIFY( bc11.first.nargs == 1 ); |
| VERIFY( bc11.first.alloc_id == 2 ); |
| VERIFY( bc11.second.nargs == 1 ); |
| VERIFY( bc11.second.alloc_id == 2 ); |
| auto cb1b = std::make_obj_using_allocator<pair<C, B>>(alloc2, f, B{}); |
| VERIFY( cb1b.first.nargs == 1 ); |
| VERIFY( cb1b.first.alloc_id == 2 ); |
| VERIFY( cb1b.second.nargs == 0 ); |
| VERIFY( cb1b.second.alloc_id == 2 ); |
| auto cccc |
| = std::make_obj_using_allocator<pair<C, const C>>(alloc1, C{}, C{}); |
| VERIFY( cccc.first.nargs == 0 ); |
| VERIFY( cccc.first.alloc_id == 1 ); |
| VERIFY( cccc.second.nargs == 0 ); |
| VERIFY( cccc.second.alloc_id == 1 ); |
| |
| pair<float&, A> p1a(f, A{}); |
| pair<float&, float&> p11(f, f); |
| auto aa1a = std::make_obj_using_allocator<pair<A, A>>(alloc1, p1a); |
| VERIFY( aa1a.first.nargs == 1 ); |
| VERIFY( aa1a.first.alloc_id == -1 ); |
| VERIFY( aa1a.second.nargs == 0 ); |
| VERIFY( aa1a.second.alloc_id == -1 ); |
| auto ab11 = std::make_obj_using_allocator<pair<A, B>>(alloc1, p11); |
| VERIFY( ab11.first.nargs == 1 ); |
| VERIFY( ab11.first.alloc_id == -1 ); |
| VERIFY( ab11.second.nargs == 1 ); |
| VERIFY( ab11.second.alloc_id == 1 ); |
| auto cb11 = std::make_obj_using_allocator<pair<C, B>>(alloc2, p11); |
| VERIFY( cb11.first.nargs == 1 ); |
| VERIFY( cb11.first.alloc_id == 2 ); |
| VERIFY( cb11.second.nargs == 1 ); |
| VERIFY( cb11.second.alloc_id == 2 ); |
| |
| auto bcbc = std::make_obj_using_allocator<pair<B, C>>(alloc2, pair<B, C>()); |
| VERIFY( bcbc.first.nargs == 0 ); |
| VERIFY( bcbc.first.alloc_id == 2 ); |
| VERIFY( bcbc.second.nargs == 0 ); |
| VERIFY( bcbc.second.alloc_id == 2 ); |
| |
| auto cc11 = std::make_obj_using_allocator<pair<C, B>>(alloc2, std::move(p11)); |
| VERIFY( cc11.first.nargs == 1 ); |
| VERIFY( cc11.first.alloc_id == 2 ); |
| VERIFY( cc11.second.nargs == 1 ); |
| VERIFY( cc11.second.alloc_id == 2 ); |
| } |
| |
| void |
| test07() |
| { |
| using nested_pair = std::pair<const std::pair<B, const B>, C>; |
| auto p = std::make_obj_using_allocator<const nested_pair>(alloc1); |
| VERIFY( p.first.first.alloc_id == 1 ); |
| VERIFY( p.first.second.alloc_id == 1 ); |
| VERIFY( p.second.alloc_id == 1 ); |
| } |
| |
| void |
| test08() |
| { |
| // LWG DR 3187. |
| // P0591R4 reverted DR 2586 fixes to scoped_allocator_adaptor::construct() |
| |
| struct X { |
| using allocator_type = std::allocator<X>; |
| X(std::allocator_arg_t, allocator_type&&) { } |
| X(const allocator_type&) { } |
| }; |
| |
| std::allocator<X> a; |
| std::make_obj_using_allocator<X>(a); |
| } |
| |
| int |
| main() |
| { |
| test01(); |
| test02(); |
| test03(); |
| test04(); |
| test05(); |
| test06(); |
| test07(); |
| test08(); |
| } |