1 | // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s |
2 | // expected-no-diagnostics |
3 | |
4 | // Example bind 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 | // Creation functions |
93 | template<typename T> |
94 | struct make_tuple_result { |
95 | typedef T type; |
96 | }; |
97 | |
98 | template<typename T> |
99 | struct make_tuple_result<reference_wrapper<T> > { |
100 | typedef T& type; |
101 | }; |
102 | |
103 | template<typename... Values> |
104 | tuple<typename make_tuple_result<Values>::type...> |
105 | make_tuple(const Values&... values) { |
106 | return tuple<typename make_tuple_result<Values>::type...>(values...); |
107 | } |
108 | |
109 | template<typename... Values> |
110 | tuple<Values&...> tie(Values&... values) { |
111 | return tuple<Values&...>(values...); |
112 | } |
113 | |
114 | // Helper classes |
115 | template<typename Tuple> struct tuple_size; |
116 | |
117 | template<typename... Values> struct tuple_size<tuple<Values...> > { |
118 | static const int value = sizeof...(Values); |
119 | }; |
120 | |
121 | template<int I, typename Tuple> struct tuple_element; |
122 | |
123 | template<int I, typename Head, typename... Tail> |
124 | struct tuple_element<I, tuple<Head, Tail...> > { |
125 | typedef typename tuple_element<I-1, tuple<Tail...> >::type type; |
126 | }; |
127 | |
128 | template<typename Head, typename... Tail> |
129 | struct tuple_element<0, tuple<Head, Tail...> > { |
130 | typedef Head type; |
131 | }; |
132 | |
133 | // Element access |
134 | template<int I, typename Tuple> class get_impl; |
135 | template<int I, typename Head, typename... Values> |
136 | class get_impl<I, tuple<Head, Values...> > { |
137 | typedef typename tuple_element<I-1, tuple<Values...> >::type Element; |
138 | typedef typename add_reference<Element>::type RJ; |
139 | typedef typename add_const_reference<Element>::type PJ; |
140 | typedef get_impl<I-1, tuple<Values...> > Next; |
141 | public: |
142 | static RJ get(tuple<Head, Values...>& t) { return Next::get(t.tail()); } |
143 | static PJ get(const tuple<Head, Values...>& t) { return Next::get(t.tail()); } |
144 | }; |
145 | |
146 | template<typename Head, typename... Values> |
147 | class get_impl<0, tuple<Head, Values...> > { |
148 | typedef typename add_reference<Head>::type RJ; |
149 | typedef typename add_const_reference<Head>::type PJ; |
150 | public: |
151 | static RJ get(tuple<Head, Values...>& t) { return t.head(); } |
152 | static PJ get(const tuple<Head, Values...>& t) { return t.head(); } |
153 | }; |
154 | |
155 | template<int I, typename... Values> typename add_reference< |
156 | typename tuple_element<I, tuple<Values...> >::type >::type |
157 | get(tuple<Values...>& t) { |
158 | return get_impl<I, tuple<Values...> >::get(t); |
159 | } |
160 | |
161 | template<int I, typename... Values> typename add_const_reference< |
162 | typename tuple_element<I, tuple<Values...> >::type >::type |
163 | get(const tuple<Values...>& t) { |
164 | return get_impl<I, tuple<Values...> >::get(t); |
165 | } |
166 | |
167 | // Relational operators |
168 | inline bool operator==(const tuple<>&, const tuple<>&) { return true; } |
169 | |
170 | template<typename T, typename... TTail, typename U, typename... UTail> |
171 | bool operator==(const tuple<T, TTail...>& t, const tuple<U, UTail...>& u) { |
172 | return t.head() == u.head() && t.tail() == u.tail(); |
173 | } |
174 | |
175 | template<typename... TValues, typename... UValues> |
176 | bool operator!=(const tuple<TValues...>& t, const tuple<UValues...>& u) { |
177 | return !(t == u); |
178 | } |
179 | |
180 | inline bool operator<(const tuple<>&, const tuple<>&) { return false; } |
181 | |
182 | template<typename T, typename... TTail, typename U, typename... UTail> |
183 | bool operator<(const tuple<T, TTail...>& t, const tuple<U, UTail...>& u) { |
184 | return (t.head() < u.head() || (!(t.head() < u.head()) && t.tail() < u.tail())); |
185 | } |
186 | |
187 | template<typename... TValues, typename... UValues> |
188 | bool operator>(const tuple<TValues...>& t, const tuple<UValues...>& u) { |
189 | return u < t; |
190 | } |
191 | |
192 | template<typename... TValues, typename... UValues> |
193 | bool operator<=(const tuple<TValues...>& t, const tuple<UValues...>& u) { |
194 | return !(u < t); |
195 | } |
196 | |
197 | template<typename... TValues, typename... UValues> |
198 | bool operator>=(const tuple<TValues...>& t, const tuple<UValues...>& u) { |
199 | return !(t < u); |
200 | } |
201 | |
202 | // make_indices helper |
203 | template<int...> struct int_tuple {}; |
204 | // make_indexes impl is a helper for make_indexes |
205 | template<int I, typename IntTuple, typename... Types> struct make_indexes_impl; |
206 | |
207 | template<int I, int... Indexes, typename T, typename... Types> |
208 | struct make_indexes_impl<I, int_tuple<Indexes...>, T, Types...> { |
209 | typedef typename make_indexes_impl<I+1, int_tuple<Indexes..., I>, Types...>::type type; |
210 | }; |
211 | |
212 | template<int I, int... Indexes> |
213 | struct make_indexes_impl<I, int_tuple<Indexes...> > { |
214 | typedef int_tuple<Indexes...> type; |
215 | }; |
216 | |
217 | template<typename... Types> |
218 | struct make_indexes : make_indexes_impl<0, int_tuple<>, Types...> { |
219 | }; |
220 | |
221 | // Bind |
222 | template<typename T> struct is_bind_expression { |
223 | static const bool value = false; |
224 | }; |
225 | |
226 | template<typename T> struct is_placeholder { |
227 | static const int value = 0; |
228 | }; |
229 | |
230 | |
231 | template<typename F, typename... BoundArgs> class bound_functor { |
232 | typedef typename make_indexes<BoundArgs...>::type indexes; |
233 | public: |
234 | typedef typename F::result_type result_type; |
235 | explicit bound_functor(const F& f, const BoundArgs&... bound_args) |
236 | : f(f), bound_args(bound_args...) { } template<typename... Args> |
237 | typename F::result_type operator()(Args&... args); |
238 | private: F f; |
239 | tuple<BoundArgs...> bound_args; |
240 | }; |
241 | |
242 | template<typename F, typename... BoundArgs> |
243 | inline bound_functor<F, BoundArgs...> bind(const F& f, const BoundArgs&... bound_args) { |
244 | return bound_functor<F, BoundArgs...>(f, bound_args...); |
245 | } |
246 | |
247 | template<typename F, typename ...BoundArgs> |
248 | struct is_bind_expression<bound_functor<F, BoundArgs...> > { |
249 | static const bool value = true; |
250 | }; |
251 | |
252 | // enable_if helper |
253 | template<bool Cond, typename T = void> |
254 | struct enable_if; |
255 | |
256 | template<typename T> |
257 | struct enable_if<true, T> { |
258 | typedef T type; |
259 | }; |
260 | |
261 | template<typename T> |
262 | struct enable_if<false, T> { }; |
263 | |
264 | // safe_tuple_element helper |
265 | template<int I, typename Tuple, typename = void> |
266 | struct safe_tuple_element { }; |
267 | |
268 | template<int I, typename... Values> |
269 | struct safe_tuple_element<I, tuple<Values...>, |
270 | typename enable_if<(I >= 0 && I < tuple_size<tuple<Values...> >::value)>::type> { |
271 | typedef typename tuple_element<I, tuple<Values...> >::type type; |
272 | }; |
273 | |
274 | // mu |
275 | template<typename Bound, typename... Args> |
276 | inline typename safe_tuple_element<is_placeholder<Bound>::value -1, |
277 | tuple<Args...> >::type |
278 | mu(Bound& bound_arg, const tuple<Args&...>& args) { |
279 | return get<is_placeholder<Bound>::value-1>(args); |
280 | } |
281 | |
282 | template<typename T, typename... Args> |
283 | inline T& mu(reference_wrapper<T>& bound_arg, const tuple<Args&...>&) { |
284 | return bound_arg.get(); |
285 | } |
286 | |
287 | template<typename F, int... Indexes, typename... Args> |
288 | inline typename F::result_type |
289 | unwrap_and_forward(F& f, int_tuple<Indexes...>, const tuple<Args&...>& args) { |
290 | return f(get<Indexes>(args)...); |
291 | } |
292 | |
293 | template<typename Bound, typename... Args> |
294 | inline typename enable_if<is_bind_expression<Bound>::value, |
295 | typename Bound::result_type>::type |
296 | mu(Bound& bound_arg, const tuple<Args&...>& args) { |
297 | typedef typename make_indexes<Args...>::type Indexes; |
298 | return unwrap_and_forward(bound_arg, Indexes(), args); |
299 | } |
300 | |
301 | template<typename T> |
302 | struct is_reference_wrapper { |
303 | static const bool value = false; |
304 | }; |
305 | |
306 | template<typename T> |
307 | struct is_reference_wrapper<reference_wrapper<T>> { |
308 | static const bool value = true; |
309 | }; |
310 | |
311 | template<typename Bound, typename... Args> |
312 | inline typename enable_if<(!is_bind_expression<Bound>::value |
313 | && !is_placeholder<Bound>::value |
314 | && !is_reference_wrapper<Bound>::value), |
315 | Bound&>::type |
316 | mu(Bound& bound_arg, const tuple<Args&...>&) { |
317 | return bound_arg; |
318 | } |
319 | |
320 | template<typename F, typename... BoundArgs, int... Indexes, typename... Args> |
321 | typename F::result_type apply_functor(F& f, tuple<BoundArgs...>& bound_args, |
322 | int_tuple<Indexes...>, |
323 | const tuple<Args&...>& args) { |
324 | return f(mu(get<Indexes>(bound_args), args)...); |
325 | } |
326 | |
327 | template<typename F, typename... BoundArgs> |
328 | template<typename... Args> |
329 | typename F::result_type bound_functor<F, BoundArgs...>::operator()(Args&... args) { |
330 | return apply_functor(f, bound_args, indexes(), tie(args...)); |
331 | } |
332 | |
333 | template<int N> struct placeholder { }; |
334 | template<int N> |
335 | struct is_placeholder<placeholder<N>> { |
336 | static const int value = N; |
337 | }; |
338 | |
339 | template<typename T> |
340 | struct plus { |
341 | typedef T result_type; |
342 | |
343 | T operator()(T x, T y) { return x + y; } |
344 | }; |
345 | |
346 | placeholder<1> _1; |
347 | |
348 | // Test bind |
349 | void test_bind() { |
350 | int x = 17; |
351 | int y = 25; |
352 | bind(plus<int>(), x, _1)(y); |
353 | } |
354 | |