1 | // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s |
2 | // expected-no-diagnostics |
3 | |
4 | // Example tuple implementation from the variadic templates proposal, |
5 | // ISO C++ committee document number N2080. |
6 | |
7 | // Helper type traits |
8 | template<typename T> |
9 | struct add_reference { |
10 | typedef T &type; |
11 | }; |
12 | |
13 | template<typename T> |
14 | struct add_reference<T&> { |
15 | typedef T &type; |
16 | }; |
17 | |
18 | template<typename T> |
19 | struct add_const_reference { |
20 | typedef T const &type; |
21 | }; |
22 | |
23 | template<typename T> |
24 | struct add_const_reference<T&> { |
25 | typedef T &type; |
26 | }; |
27 | |
28 | template<typename T, typename U> |
29 | struct is_same { |
30 | static const bool value = false; |
31 | }; |
32 | |
33 | template<typename T> |
34 | struct is_same<T, T> { |
35 | static const bool value = true; |
36 | }; |
37 | |
38 | template<typename T> |
39 | class reference_wrapper { |
40 | T *ptr; |
41 | |
42 | public: |
43 | reference_wrapper(T& t) : ptr(&t) { } |
44 | operator T&() const { return *ptr; } |
45 | }; |
46 | |
47 | template<typename T> reference_wrapper<T> ref(T& t) { |
48 | return reference_wrapper<T>(t); |
49 | } |
50 | template<typename T> reference_wrapper<const T> cref(const T& t) { |
51 | return reference_wrapper<const T>(t); |
52 | } |
53 | |
54 | template<typename... Values> class tuple; |
55 | |
56 | // Basis case: zero-length tuple |
57 | template<> class tuple<> { }; |
58 | |
59 | template<typename Head, typename... Tail> |
60 | class tuple<Head, Tail...> : private tuple<Tail...> { |
61 | typedef tuple<Tail...> inherited; |
62 | |
63 | public: |
64 | tuple() { } |
65 | // implicit copy-constructor is okay |
66 | |
67 | // Construct tuple from separate arguments. |
68 | tuple(typename add_const_reference<Head>::type v, |
69 | typename add_const_reference<Tail>::type... vtail) |
70 | : m_head(v), inherited(vtail...) { } |
71 | |
72 | // Construct tuple from another tuple. |
73 | template<typename... VValues> tuple(const tuple<VValues...>& other) |
74 | : m_head(other.head()), inherited(other.tail()) { } |
75 | |
76 | template<typename... VValues> tuple& |
77 | operator=(const tuple<VValues...>& other) { |
78 | m_head = other.head(); |
79 | tail() = other.tail(); |
80 | return *this; |
81 | } |
82 | |
83 | typename add_reference<Head>::type head() { return m_head; } |
84 | typename add_reference<const Head>::type head() const { return m_head; } |
85 | inherited& tail() { return *this; } |
86 | const inherited& tail() const { return *this; } |
87 | |
88 | protected: |
89 | Head m_head; |
90 | }; |
91 | |
92 | void test_tuple() { |
93 | tuple<> t0a; |
94 | tuple<> t0b(t0a); |
95 | t0a = t0b; |
96 | |
97 | tuple<int> t1a; |
98 | tuple<int> t1b(17); |
99 | tuple<int> t1c(t1b); |
100 | t1a = t1b; |
101 | |
102 | tuple<float> t1d(3.14159); |
103 | tuple<float> t1e(t1d); |
104 | t1d = t1e; |
105 | |
106 | int i; |
107 | float f; |
108 | double d; |
109 | tuple<int*, float*, double*> t3a(&i, &f, &d); |
110 | } |
111 | |
112 | // Creation functions |
113 | template<typename T> |
114 | struct make_tuple_result { |
115 | typedef T type; |
116 | }; |
117 | |
118 | template<typename T> |
119 | struct make_tuple_result<reference_wrapper<T> > { |
120 | typedef T& type; |
121 | }; |
122 | |
123 | template<typename... Values> |
124 | tuple<typename make_tuple_result<Values>::type...> |
125 | make_tuple(const Values&... values) { |
126 | return tuple<typename make_tuple_result<Values>::type...>(values...); |
127 | } |
128 | |
129 | template<typename... Values> |
130 | tuple<Values&...> tie(Values&... values) { |
131 | return tuple<Values&...>(values...); |
132 | } |
133 | |
134 | template<typename T> const T *addr(const T& ref) { return &ref; } |
135 | void test_creation_functions() { |
136 | int i; |
137 | float f; |
138 | double d; |
139 | const tuple<int, float&, const double&> *t3p = addr(make_tuple(i, ref(f), cref(d))); |
140 | const tuple<int&, float&, double&> *t3q = addr(tie(i, f, d)); |
141 | } |
142 | |
143 | // Helper classes |
144 | template<typename Tuple> struct tuple_size; |
145 | |
146 | template<typename... Values> struct tuple_size<tuple<Values...> > { |
147 | static const int value = sizeof...(Values); |
148 | }; |
149 | |
150 | int check_tuple_size_0[tuple_size<tuple<> >::value == 0? 1 : -1]; |
151 | int check_tuple_size_1[tuple_size<tuple<int>>::value == 1? 1 : -1]; |
152 | int check_tuple_size_2[tuple_size<tuple<float, double>>::value == 2? 1 : -1]; |
153 | int check_tuple_size_3[tuple_size<tuple<char, unsigned char, signed char>>::value == 3? 1 : -1]; |
154 | |
155 | template<int I, typename Tuple> struct tuple_element; |
156 | |
157 | template<int I, typename Head, typename... Tail> |
158 | struct tuple_element<I, tuple<Head, Tail...> > { |
159 | typedef typename tuple_element<I-1, tuple<Tail...> >::type type; |
160 | }; |
161 | |
162 | template<typename Head, typename... Tail> |
163 | struct tuple_element<0, tuple<Head, Tail...> > { |
164 | typedef Head type; |
165 | }; |
166 | |
167 | int check_tuple_element_0[is_same<tuple_element<0, tuple<int&, float, double>>::type, |
168 | int&>::value? 1 : -1]; |
169 | |
170 | int check_tuple_element_1[is_same<tuple_element<1, tuple<int&, float, double>>::type, |
171 | float>::value? 1 : -1]; |
172 | |
173 | int check_tuple_element_2[is_same<tuple_element<2, tuple<int&, float, double>>::type, |
174 | double>::value? 1 : -1]; |
175 | |
176 | // Element access |
177 | template<int I, typename Tuple> class get_impl; |
178 | template<int I, typename Head, typename... Values> |
179 | class get_impl<I, tuple<Head, Values...> > { |
180 | typedef typename tuple_element<I-1, tuple<Values...> >::type Element; |
181 | typedef typename add_reference<Element>::type RJ; |
182 | typedef typename add_const_reference<Element>::type PJ; |
183 | typedef get_impl<I-1, tuple<Values...> > Next; |
184 | public: |
185 | static RJ get(tuple<Head, Values...>& t) { return Next::get(t.tail()); } |
186 | static PJ get(const tuple<Head, Values...>& t) { return Next::get(t.tail()); } |
187 | }; |
188 | |
189 | template<typename Head, typename... Values> |
190 | class get_impl<0, tuple<Head, Values...> > { |
191 | typedef typename add_reference<Head>::type RJ; |
192 | typedef typename add_const_reference<Head>::type PJ; |
193 | public: |
194 | static RJ get(tuple<Head, Values...>& t) { return t.head(); } |
195 | static PJ get(const tuple<Head, Values...>& t) { return t.head(); } |
196 | }; |
197 | |
198 | template<int I, typename... Values> typename add_reference< |
199 | typename tuple_element<I, tuple<Values...> >::type >::type |
200 | get(tuple<Values...>& t) { |
201 | return get_impl<I, tuple<Values...> >::get(t); |
202 | } |
203 | |
204 | template<int I, typename... Values> typename add_const_reference< |
205 | typename tuple_element<I, tuple<Values...> >::type >::type |
206 | get(const tuple<Values...>& t) { |
207 | return get_impl<I, tuple<Values...> >::get(t); |
208 | } |
209 | |
210 | void test_element_access(tuple<int*, float*, double*&> t3) { |
211 | int i; |
212 | float f; |
213 | double d; |
214 | get<0>(t3) = &i; |
215 | get<1>(t3) = &f; |
216 | get<2>(t3) = &d; |
217 | } |
218 | |
219 | // Relational operators |
220 | inline bool operator==(const tuple<>&, const tuple<>&) { return true; } |
221 | |
222 | template<typename T, typename... TTail, typename U, typename... UTail> |
223 | bool operator==(const tuple<T, TTail...>& t, const tuple<U, UTail...>& u) { |
224 | return t.head() == u.head() && t.tail() == u.tail(); |
225 | } |
226 | |
227 | template<typename... TValues, typename... UValues> |
228 | bool operator!=(const tuple<TValues...>& t, const tuple<UValues...>& u) { |
229 | return !(t == u); |
230 | } |
231 | |
232 | inline bool operator<(const tuple<>&, const tuple<>&) { return false; } |
233 | |
234 | template<typename T, typename... TTail, typename U, typename... UTail> |
235 | bool operator<(const tuple<T, TTail...>& t, const tuple<U, UTail...>& u) { |
236 | return (t.head() < u.head() || (!(t.head() < u.head()) && t.tail() < u.tail())); |
237 | } |
238 | |
239 | template<typename... TValues, typename... UValues> |
240 | bool operator>(const tuple<TValues...>& t, const tuple<UValues...>& u) { |
241 | return u < t; |
242 | } |
243 | |
244 | template<typename... TValues, typename... UValues> |
245 | bool operator<=(const tuple<TValues...>& t, const tuple<UValues...>& u) { |
246 | return !(u < t); |
247 | } |
248 | |
249 | template<typename... TValues, typename... UValues> |
250 | bool operator>=(const tuple<TValues...>& t, const tuple<UValues...>& u) { |
251 | return !(t < u); |
252 | } |
253 | |
254 | void test_relational_operators(tuple<int*, float*, double*> t3) { |
255 | (void)(t3 == t3); |
256 | (void)(t3 != t3); |
257 | (void)(t3 < t3); |
258 | (void)(t3 <= t3); |
259 | (void)(t3 >= t3); |
260 | (void)(t3 > t3); |
261 | }; |
262 | |