1 // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
3 // This is a collection of various template metafunctions involving
4 // variadic templates, which are meant to exercise common use cases.
5 template<typename T
, typename U
>
7 static const bool value
= false;
11 struct is_same
<T
, T
> {
12 static const bool value
= true;
15 template<typename
...> struct tuple
{ };
16 template<int ...> struct int_tuple
{ };
17 template<typename T
, typename U
> struct pair
{ };
20 template<typename Head
, typename
...Tail
>
22 static const unsigned value
= 1 + count
<Tail
...>::value
;
27 static const unsigned value
= 1;
30 int check1
[count
<int>::value
== 1? 1 : -1];
31 int check2
[count
<float, double>::value
== 2? 1 : -1];
32 int check3
[count
<char, signed char, unsigned char>::value
== 3? 1 : -1];
35 namespace CountWithPackExpansion
{
36 template<typename
...> struct count
;
38 template<typename Head
, typename
...Tail
>
39 struct count
<Head
, Tail
...> {
40 static const unsigned value
= 1 + count
<Tail
...>::value
;
45 static const unsigned value
= 0;
48 int check0
[count
<>::value
== 0? 1 : -1];
49 int check1
[count
<int>::value
== 1? 1 : -1];
50 int check2
[count
<float, double>::value
== 2? 1 : -1];
51 int check3
[count
<char, signed char, unsigned char>::value
== 3? 1 : -1];
55 // Simple metafunction that replaces the template arguments of
56 // template template parameters with 'int'.
58 struct EverythingToInt
;
60 template<template<typename
...> class TT
, typename T1
, typename T2
>
61 struct EverythingToInt
<TT
<T1
, T2
> > {
62 typedef TT
<int, int> type
;
65 int check0
[is_same
<EverythingToInt
<tuple
<double, float>>::type
,
66 tuple
<int, int>>::value
? 1 : -1];
70 template<int ...Values
>
71 struct double_values
{
72 typedef int_tuple
<Values
*2 ...> type
;
75 int check0
[is_same
<double_values
<1, 2, -3>::type
,
76 int_tuple
<2, 4, -6>>::value
? 1 : -1];
78 template<int ...Values
>
80 typedef int_tuple
<(Values
*Values
)...> type
;
83 int check1
[is_same
<square
<1, 2, -3>::type
,
84 int_tuple
<1, 4, 9>>::value
? 1 : -1];
86 template<typename IntTuple
> struct square_tuple
;
88 template<int ...Values
>
89 struct square_tuple
<int_tuple
<Values
...>> {
90 typedef int_tuple
<(Values
*Values
)...> type
;
93 int check2
[is_same
<square_tuple
<int_tuple
<1, 2, -3> >::type
,
94 int_tuple
<1, 4, 9>>::value
? 1 : -1];
96 template<int ...Values
> struct sum
;
98 template<int First
, int ...Rest
>
99 struct sum
<First
, Rest
...> {
100 static const int value
= First
+ sum
<Rest
...>::value
;
105 static const int value
= 0;
108 int check3
[sum
<1, 2, 3, 4, 5>::value
== 15? 1 : -1];
110 template<int ... Values
>
113 return sum
<Values
...>::value
;
118 lazy_sum
<1, 2, 3, 4, 5>()();
123 template<typename T
, T
... V
> struct add
;
125 template<typename T
, T i
, T
... V
>
126 struct add
<T
, i
, V
...> {
127 static const T value
= i
+ add
<T
, V
...>::value
;
132 static const T value
= T();
135 template<typename T
, T
... V
>
138 static const T value
= add
<T
, V
...>::value
;
143 struct ListI
: public List
<int, V
...> {
146 int check0
[ListI
<1, 2, 3>::sum::value
== 6? 1 : -1];
150 template<unsigned I
, unsigned N
, typename IntTuple
>
151 struct build_indices_impl
;
153 template<unsigned I
, unsigned N
, int ...Indices
>
154 struct build_indices_impl
<I
, N
, int_tuple
<Indices
...> >
155 : build_indices_impl
<I
+1, N
, int_tuple
<Indices
..., I
> > {
158 template<unsigned N
, int ...Indices
>
159 struct build_indices_impl
<N
, N
, int_tuple
<Indices
...> > {
160 typedef int_tuple
<Indices
...> type
;
164 struct build_indices
: build_indices_impl
<0, N
, int_tuple
<> > { };
166 int check0
[is_same
<build_indices
<5>::type
,
167 int_tuple
<0, 1, 2, 3, 4>>::value
? 1 : -1];
170 namespace TemplateTemplateApply
{
171 template<typename T
, template<class> class ...Meta
>
173 typedef tuple
<typename Meta
<T
>::type
...> type
;
177 struct add_reference
{
188 typedef const T type
;
191 int check0
[is_same
<apply_each
<int,
192 add_reference
, add_pointer
, add_const
>::type
,
193 tuple
<int&, int*, int const>>::value
? 1 : -1];
195 template<typename T
, template<class> class ...Meta
>
196 struct apply_each_indirect
{
197 typedef typename apply_each
<T
, Meta
...>::type type
;
200 int check1
[is_same
<apply_each_indirect
<int, add_reference
, add_pointer
,
202 tuple
<int&, int*, int const>>::value
? 1 : -1];
204 template<typename T
, typename
...Meta
>
205 struct apply_each_nested
{
206 typedef typename apply_each
<T
, Meta::template apply
...>::type type
;
209 struct add_reference_meta
{
216 struct add_pointer_meta
{
223 struct add_const_meta
{
226 typedef const T type
;
230 int check2
[is_same
<apply_each_nested
<int, add_reference_meta
,
231 add_pointer_meta
, add_const_meta
>::type
,
232 tuple
<int&, int*, int const>>::value
? 1 : -1];
236 namespace FunctionTypes
{
237 template<typename FunctionType
>
240 template<typename R
, typename
...Types
>
241 struct Arity
<R(Types
...)> {
242 static const unsigned value
= sizeof...(Types
);
245 template<typename R
, typename
...Types
>
246 struct Arity
<R(Types
......)> { // expected-warning {{varargs}} expected-note {{pack}} expected-note {{insert ','}}
247 static const unsigned value
= sizeof...(Types
);
250 template<typename R
, typename T1
, typename T2
, typename T3
, typename T4
>
251 struct Arity
<R(T1
, T2
, T3
, T4
)>; // expected-note{{template is declared here}}
253 int check0
[Arity
<int()>::value
== 0? 1 : -1];
254 int check1
[Arity
<int(float, double)>::value
== 2? 1 : -1];
255 int check2
[Arity
<int(float...)>::value
== 1? 1 : -1];
256 int check3
[Arity
<int(float, double, long double...)>::value
== 3? 1 : -1];
257 Arity
<int(float, double, long double, char)> check4
; // expected-error{{implicit instantiation of undefined template 'FunctionTypes::Arity<int (float, double, long double, char)>'}}
260 namespace SuperReplace
{
262 struct replace_with_int
{
266 template<template<typename
...> class TT
, typename
...Types
>
267 struct replace_with_int
<TT
<Types
...>> {
268 typedef TT
<typename replace_with_int
<Types
>::type
...> type
;
271 int check0
[is_same
<replace_with_int
<pair
<tuple
<float, double, short>,
272 pair
<char, unsigned char>>>::type
,
273 pair
<tuple
<int, int, int>, pair
<int, int>>>::value
? 1 : -1];