1 // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
2 // expected-no-diagnostics
4 // Example bind implementation from the variadic templates proposal,
5 // ISO C++ committee document number N2080.
14 struct add_reference
<T
&> {
19 struct add_const_reference
{
20 typedef T
const &type
;
24 struct add_const_reference
<T
&> {
28 template<typename T
, typename U
>
30 static const bool value
= false;
34 struct is_same
<T
, T
> {
35 static const bool value
= true;
39 class reference_wrapper
{
43 reference_wrapper(T
& t
) : ptr(&t
) { }
44 operator T
&() const { return *ptr
; }
47 template<typename T
> reference_wrapper
<T
> ref(T
& t
) {
48 return reference_wrapper
<T
>(t
);
50 template<typename T
> reference_wrapper
<const T
> cref(const T
& t
) {
51 return reference_wrapper
<const T
>(t
);
54 template<typename
... Values
> class tuple
;
56 // Basis case: zero-length tuple
57 template<> class tuple
<> { };
59 template<typename Head
, typename
... Tail
>
60 class tuple
<Head
, Tail
...> : private tuple
<Tail
...> {
61 typedef tuple
<Tail
...> inherited
;
65 // implicit copy-constructor is okay
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
...) { }
72 // Construct tuple from another tuple.
73 template<typename
... VValues
> tuple(const tuple
<VValues
...>& other
)
74 : m_head(other
.head()), inherited(other
.tail()) { }
76 template<typename
... VValues
> tuple
&
77 operator=(const tuple
<VValues
...>& other
) {
78 m_head
= other
.head();
79 tail() = other
.tail();
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; }
94 struct make_tuple_result
{
99 struct make_tuple_result
<reference_wrapper
<T
> > {
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
...);
109 template<typename
... Values
>
110 tuple
<Values
&...> tie(Values
&... values
) {
111 return tuple
<Values
&...>(values
...);
115 template<typename Tuple
> struct tuple_size
;
117 template<typename
... Values
> struct tuple_size
<tuple
<Values
...> > {
118 static const int value
= sizeof...(Values
);
121 template<int I
, typename Tuple
> struct tuple_element
;
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
;
128 template<typename Head
, typename
... Tail
>
129 struct tuple_element
<0, tuple
<Head
, Tail
...> > {
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
;
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()); }
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
;
151 static RJ
get(tuple
<Head
, Values
...>& t
) { return t
.head(); }
152 static PJ
get(const tuple
<Head
, Values
...>& t
) { return t
.head(); }
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
);
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
);
167 // Relational operators
168 inline bool operator==(const tuple
<>&, const tuple
<>&) { return true; }
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();
175 template<typename
... TValues
, typename
... UValues
>
176 bool operator!=(const tuple
<TValues
...>& t
, const tuple
<UValues
...>& u
) {
180 inline bool operator<(const tuple
<>&, const tuple
<>&) { return false; }
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()));
187 template<typename
... TValues
, typename
... UValues
>
188 bool operator>(const tuple
<TValues
...>& t
, const tuple
<UValues
...>& u
) {
192 template<typename
... TValues
, typename
... UValues
>
193 bool operator<=(const tuple
<TValues
...>& t
, const tuple
<UValues
...>& u
) {
197 template<typename
... TValues
, typename
... UValues
>
198 bool operator>=(const tuple
<TValues
...>& t
, const tuple
<UValues
...>& u
) {
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
;
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
;
212 template<int I
, int... Indexes
>
213 struct make_indexes_impl
<I
, int_tuple
<Indexes
...> > {
214 typedef int_tuple
<Indexes
...> type
;
217 template<typename
... Types
>
218 struct make_indexes
: make_indexes_impl
<0, int_tuple
<>, Types
...> {
222 template<typename T
> struct is_bind_expression
{
223 static const bool value
= false;
226 template<typename T
> struct is_placeholder
{
227 static const int value
= 0;
231 template<typename F
, typename
... BoundArgs
> class bound_functor
{
232 typedef typename make_indexes
<BoundArgs
...>::type indexes
;
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
);
239 tuple
<BoundArgs
...> bound_args
;
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
...);
247 template<typename F
, typename
...BoundArgs
>
248 struct is_bind_expression
<bound_functor
<F
, BoundArgs
...> > {
249 static const bool value
= true;
253 template<bool Cond
, typename T
= void>
257 struct enable_if
<true, T
> {
262 struct enable_if
<false, T
> { };
264 // safe_tuple_element helper
265 template<int I
, typename Tuple
, typename
= void>
266 struct safe_tuple_element
{ };
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
;
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
);
282 template<typename T
, typename
... Args
>
283 inline T
& mu(reference_wrapper
<T
>& bound_arg
, const tuple
<Args
&...>&) {
284 return bound_arg
.get();
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
)...);
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
);
302 struct is_reference_wrapper
{
303 static const bool value
= false;
307 struct is_reference_wrapper
<reference_wrapper
<T
>> {
308 static const bool value
= true;
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
),
316 mu(Bound
& bound_arg
, const tuple
<Args
&...>&) {
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
)...);
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
...));
333 template<int N
> struct placeholder
{ };
335 struct is_placeholder
<placeholder
<N
>> {
336 static const int value
= N
;
341 typedef T result_type
;
343 T
operator()(T x
, T y
) { return x
+ y
; }
352 bind(plus
<int>(), x
, _1
)(y
);