1 // Copyright (C) 2016-2018 Free Software Foundation, Inc.
2 //
3 // This file is part of the GNU ISO C++ Library. This library is free
4 // software; you can redistribute it and/or modify it under the
5 // terms of the GNU General Public License as published by the
6 // Free Software Foundation; either version 3, or (at your option)
7 // any later version.
8
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13
14 // You should have received a copy of the GNU General Public License along
15 // with this library; see the file COPYING3. If not see
16 // <http://www.gnu.org/licenses/>.
17
18 // { dg-do compile { target c++11 } }
19
20 #include <scoped_allocator>
21
22 template<typename T>
23 struct alloc
24 {
25 using value_type = T;
26 alloc() = default;
27 template<typename U>
allocalloc28 alloc(alloc<U>) { }
29 T* allocate(std::size_t);
30 void deallocate(T*, std::size_t);
31 };
32
33 template<typename T, typename U>
operator ==(alloc<T>,alloc<U>)34 bool operator==(alloc<T>, alloc<U>) { return true; }
35
36 template<typename T, typename U>
operator !=(alloc<T>,alloc<U>)37 bool operator!=(alloc<T>, alloc<U>) { return false; }
38
39 struct X
40 {
41 using allocator_type = alloc<int>;
42 X(const allocator_type&);
43 };
44
45 template<typename A>
46 struct nested_alloc : A
47 {
48 nested_alloc() = default;
49 template<typename U>
nested_allocnested_alloc50 nested_alloc(nested_alloc<U>) { }
51
outer_allocatornested_alloc52 A& outer_allocator() { return *this; }
53
54 template<typename U, typename... Args>
constructnested_alloc55 void construct(U*, Args&&...)
56 {
57 static_assert(!std::is_same<U, X>::value,
58 "OUTERMOST should recurse and use alloc<int> to construct X");
59 }
60 };
61
62 template<typename T, typename U>
operator ==(nested_alloc<T> l,nested_alloc<U> r)63 bool operator==(nested_alloc<T> l, nested_alloc<U> r)
64 { return l.outer_allocator() == r.outer_allocator(); }
65
66 template<typename T, typename U>
operator !=(nested_alloc<T> l,nested_alloc<U> r)67 bool operator!=(nested_alloc<T> l, nested_alloc<U> r)
68 { return !(l == r); }
69
70 template<typename A>
71 using scoped_alloc = std::scoped_allocator_adaptor<A>;
72
73 void
test01()74 test01()
75 {
76 scoped_alloc<nested_alloc<alloc<int>>> a;
77 alignas(X) char buf[sizeof(X)];
78 X* p = (X*)buf;
79 // Test that OUTERMOST is recursive and doesn't just unwrap one level:
80 a.construct(p);
81 }
82
83 void
test02()84 test02()
85 {
86 scoped_alloc<scoped_alloc<nested_alloc<alloc<int>>>> a;
87 alignas(X) char buf[sizeof(X)];
88 X* p = (X*)buf;
89 // Test that OUTERMOST is recursive and doesn't just unwrap one level:
90 a.construct(p);
91 }
92