1//===----------------------------------------------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef ALLOCATORS_H
11#define ALLOCATORS_H
12
13#include <type_traits>
14#include <utility>
15
16#include "test_macros.h"
17
18#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
19
20template <class T>
21class A1
22{
23    int id_;
24public:
25    explicit A1(int id = 0) TEST_NOEXCEPT : id_(id) {}
26
27    typedef T value_type;
28
29    int id() const {return id_;}
30
31    static bool copy_called;
32    static bool move_called;
33    static bool allocate_called;
34    static std::pair<T*, std::size_t> deallocate_called;
35
36    A1(const A1& a) TEST_NOEXCEPT : id_(a.id()) {copy_called = true;}
37    A1(A1&& a)      TEST_NOEXCEPT : id_(a.id()) {move_called = true;}
38    A1& operator=(const A1& a) TEST_NOEXCEPT { id_ = a.id(); copy_called = true; return *this;}
39    A1& operator=(A1&& a)      TEST_NOEXCEPT { id_ = a.id(); move_called = true; return *this;}
40
41    template <class U>
42        A1(const A1<U>& a) TEST_NOEXCEPT : id_(a.id()) {copy_called = true;}
43    template <class U>
44        A1(A1<U>&& a) TEST_NOEXCEPT : id_(a.id()) {move_called = true;}
45
46    T* allocate(std::size_t n)
47    {
48        allocate_called = true;
49        return (T*)n;
50    }
51
52    void deallocate(T* p, std::size_t n)
53    {
54        deallocate_called = std::pair<T*, std::size_t>(p, n);
55    }
56
57    std::size_t max_size() const {return id_;}
58};
59
60template <class T> bool A1<T>::copy_called = false;
61template <class T> bool A1<T>::move_called = false;
62template <class T> bool A1<T>::allocate_called = false;
63template <class T> std::pair<T*, std::size_t> A1<T>::deallocate_called;
64
65template <class T, class U>
66inline
67bool operator==(const A1<T>& x, const A1<U>& y)
68{
69    return x.id() == y.id();
70}
71
72template <class T, class U>
73inline
74bool operator!=(const A1<T>& x, const A1<U>& y)
75{
76    return !(x == y);
77}
78
79template <class T>
80class A2
81{
82    int id_;
83public:
84    explicit A2(int id = 0) TEST_NOEXCEPT : id_(id) {}
85
86    typedef T value_type;
87
88    typedef unsigned size_type;
89    typedef int difference_type;
90
91    typedef std::true_type propagate_on_container_move_assignment;
92
93    int id() const {return id_;}
94
95    static bool copy_called;
96    static bool move_called;
97    static bool allocate_called;
98
99    A2(const A2& a) TEST_NOEXCEPT : id_(a.id()) {copy_called = true;}
100    A2(A2&& a)      TEST_NOEXCEPT : id_(a.id()) {move_called = true;}
101    A2& operator=(const A2& a) TEST_NOEXCEPT { id_ = a.id(); copy_called = true; return *this;}
102    A2& operator=(A2&& a)      TEST_NOEXCEPT { id_ = a.id(); move_called = true; return *this;}
103
104    T* allocate(std::size_t, const void* hint)
105    {
106        allocate_called = true;
107        return (T*)hint;
108    }
109};
110
111template <class T> bool A2<T>::copy_called = false;
112template <class T> bool A2<T>::move_called = false;
113template <class T> bool A2<T>::allocate_called = false;
114
115template <class T, class U>
116inline
117bool operator==(const A2<T>& x, const A2<U>& y)
118{
119    return x.id() == y.id();
120}
121
122template <class T, class U>
123inline
124bool operator!=(const A2<T>& x, const A2<U>& y)
125{
126    return !(x == y);
127}
128
129template <class T>
130class A3
131{
132    int id_;
133public:
134    explicit A3(int id = 0) TEST_NOEXCEPT : id_(id) {}
135
136    typedef T value_type;
137
138    typedef std::true_type propagate_on_container_copy_assignment;
139    typedef std::true_type propagate_on_container_swap;
140
141    int id() const {return id_;}
142
143    static bool copy_called;
144    static bool move_called;
145    static bool constructed;
146    static bool destroy_called;
147
148    A3(const A3& a) TEST_NOEXCEPT : id_(a.id()) {copy_called = true;}
149    A3(A3&& a)      TEST_NOEXCEPT : id_(a.id())  {move_called = true;}
150    A3& operator=(const A3& a) TEST_NOEXCEPT { id_ = a.id(); copy_called = true; return *this;}
151    A3& operator=(A3&& a)      TEST_NOEXCEPT { id_ = a.id(); move_called = true; return *this;}
152
153    template <class U, class ...Args>
154    void construct(U* p, Args&& ...args)
155    {
156        ::new (p) U(std::forward<Args>(args)...);
157        constructed = true;
158    }
159
160    template <class U>
161    void destroy(U* p)
162    {
163        p->~U();
164        destroy_called = true;
165    }
166
167    A3 select_on_container_copy_construction() const {return A3(-1);}
168};
169
170template <class T> bool A3<T>::copy_called = false;
171template <class T> bool A3<T>::move_called = false;
172template <class T> bool A3<T>::constructed = false;
173template <class T> bool A3<T>::destroy_called = false;
174
175template <class T, class U>
176inline
177bool operator==(const A3<T>& x, const A3<U>& y)
178{
179    return x.id() == y.id();
180}
181
182template <class T, class U>
183inline
184bool operator!=(const A3<T>& x, const A3<U>& y)
185{
186    return !(x == y);
187}
188
189#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
190
191#endif  // ALLOCATORS_H
192