1762bb9d0ad20320b9f97a841dce57ba5e8e48b07Richard Smith// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
281063a237722ae010bca325021b92436f8c56e05Douglas Gregor
381063a237722ae010bca325021b92436f8c56e05Douglas Gregor// This is a collection of various template metafunctions involving
481063a237722ae010bca325021b92436f8c56e05Douglas Gregor// variadic templates, which are meant to exercise common use cases.
581063a237722ae010bca325021b92436f8c56e05Douglas Gregortemplate<typename T, typename U>
681063a237722ae010bca325021b92436f8c56e05Douglas Gregorstruct is_same {
781063a237722ae010bca325021b92436f8c56e05Douglas Gregor  static const bool value = false;
881063a237722ae010bca325021b92436f8c56e05Douglas Gregor};
981063a237722ae010bca325021b92436f8c56e05Douglas Gregor
1081063a237722ae010bca325021b92436f8c56e05Douglas Gregortemplate<typename T>
1181063a237722ae010bca325021b92436f8c56e05Douglas Gregorstruct is_same<T, T> {
1281063a237722ae010bca325021b92436f8c56e05Douglas Gregor  static const bool value = true;
1381063a237722ae010bca325021b92436f8c56e05Douglas Gregor};
1481063a237722ae010bca325021b92436f8c56e05Douglas Gregor
1581063a237722ae010bca325021b92436f8c56e05Douglas Gregortemplate<typename...> struct tuple { };
1681063a237722ae010bca325021b92436f8c56e05Douglas Gregortemplate<int ...> struct int_tuple { };
17a03478231363c67ea0e1f4bc1bc708e064040e56Douglas Gregortemplate<typename T, typename U> struct pair { };
1881063a237722ae010bca325021b92436f8c56e05Douglas Gregor
1981063a237722ae010bca325021b92436f8c56e05Douglas Gregornamespace Count {
2081063a237722ae010bca325021b92436f8c56e05Douglas Gregor  template<typename Head, typename ...Tail>
2181063a237722ae010bca325021b92436f8c56e05Douglas Gregor  struct count {
2281063a237722ae010bca325021b92436f8c56e05Douglas Gregor    static const unsigned value = 1 + count<Tail...>::value;
2381063a237722ae010bca325021b92436f8c56e05Douglas Gregor  };
2481063a237722ae010bca325021b92436f8c56e05Douglas Gregor
2581063a237722ae010bca325021b92436f8c56e05Douglas Gregor  template<typename T>
2681063a237722ae010bca325021b92436f8c56e05Douglas Gregor  struct count<T> {
2781063a237722ae010bca325021b92436f8c56e05Douglas Gregor    static const unsigned value = 1;
2881063a237722ae010bca325021b92436f8c56e05Douglas Gregor  };
2981063a237722ae010bca325021b92436f8c56e05Douglas Gregor
3081063a237722ae010bca325021b92436f8c56e05Douglas Gregor  int check1[count<int>::value == 1? 1 : -1];
3181063a237722ae010bca325021b92436f8c56e05Douglas Gregor  int check2[count<float, double>::value == 2? 1 : -1];
3281063a237722ae010bca325021b92436f8c56e05Douglas Gregor  int check3[count<char, signed char, unsigned char>::value == 3? 1 : -1];
3381063a237722ae010bca325021b92436f8c56e05Douglas Gregor}
3481063a237722ae010bca325021b92436f8c56e05Douglas Gregor
3581063a237722ae010bca325021b92436f8c56e05Douglas Gregornamespace CountWithPackExpansion {
3681063a237722ae010bca325021b92436f8c56e05Douglas Gregor  template<typename ...> struct count;
3781063a237722ae010bca325021b92436f8c56e05Douglas Gregor
3881063a237722ae010bca325021b92436f8c56e05Douglas Gregor  template<typename Head, typename ...Tail>
3981063a237722ae010bca325021b92436f8c56e05Douglas Gregor  struct count<Head, Tail...> {
4081063a237722ae010bca325021b92436f8c56e05Douglas Gregor    static const unsigned value = 1 + count<Tail...>::value;
4181063a237722ae010bca325021b92436f8c56e05Douglas Gregor  };
4281063a237722ae010bca325021b92436f8c56e05Douglas Gregor
4381063a237722ae010bca325021b92436f8c56e05Douglas Gregor  template<>
4481063a237722ae010bca325021b92436f8c56e05Douglas Gregor  struct count<> {
4581063a237722ae010bca325021b92436f8c56e05Douglas Gregor    static const unsigned value = 0;
4681063a237722ae010bca325021b92436f8c56e05Douglas Gregor  };
4781063a237722ae010bca325021b92436f8c56e05Douglas Gregor
4881063a237722ae010bca325021b92436f8c56e05Douglas Gregor  int check0[count<>::value == 0? 1 : -1];
4981063a237722ae010bca325021b92436f8c56e05Douglas Gregor  int check1[count<int>::value == 1? 1 : -1];
5081063a237722ae010bca325021b92436f8c56e05Douglas Gregor  int check2[count<float, double>::value == 2? 1 : -1];
5181063a237722ae010bca325021b92436f8c56e05Douglas Gregor  int check3[count<char, signed char, unsigned char>::value == 3? 1 : -1];
5281063a237722ae010bca325021b92436f8c56e05Douglas Gregor}
5381063a237722ae010bca325021b92436f8c56e05Douglas Gregor
5481063a237722ae010bca325021b92436f8c56e05Douglas Gregornamespace Replace {
5581063a237722ae010bca325021b92436f8c56e05Douglas Gregor  // Simple metafunction that replaces the template arguments of
5681063a237722ae010bca325021b92436f8c56e05Douglas Gregor  // template template parameters with 'int'.
5781063a237722ae010bca325021b92436f8c56e05Douglas Gregor  template<typename T>
5881063a237722ae010bca325021b92436f8c56e05Douglas Gregor  struct EverythingToInt;
5981063a237722ae010bca325021b92436f8c56e05Douglas Gregor
6081063a237722ae010bca325021b92436f8c56e05Douglas Gregor  template<template<typename ...> class TT, typename T1, typename T2>
6181063a237722ae010bca325021b92436f8c56e05Douglas Gregor  struct EverythingToInt<TT<T1, T2> > {
6281063a237722ae010bca325021b92436f8c56e05Douglas Gregor    typedef TT<int, int> type;
6381063a237722ae010bca325021b92436f8c56e05Douglas Gregor  };
6481063a237722ae010bca325021b92436f8c56e05Douglas Gregor
6581063a237722ae010bca325021b92436f8c56e05Douglas Gregor  int check0[is_same<EverythingToInt<tuple<double, float>>::type,
6681063a237722ae010bca325021b92436f8c56e05Douglas Gregor             tuple<int, int>>::value? 1 : -1];
6781063a237722ae010bca325021b92436f8c56e05Douglas Gregor}
68be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor
69dee196ef31073b40c48d60d9fa626ee1d8daaaeeDouglas Gregornamespace Math {
70be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor  template<int ...Values>
71be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor  struct double_values {
72be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor    typedef int_tuple<Values*2 ...> type;
73be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor  };
74be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor
75be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor  int check0[is_same<double_values<1, 2, -3>::type,
76be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor                     int_tuple<2, 4, -6>>::value? 1 : -1];
77be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor
78be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor  template<int ...Values>
79be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor  struct square {
80be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor    typedef int_tuple<(Values*Values)...> type;
81be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor  };
82be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor
83be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor  int check1[is_same<square<1, 2, -3>::type,
84be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor                     int_tuple<1, 4, 9>>::value? 1 : -1];
85be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor
86be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor  template<typename IntTuple> struct square_tuple;
87be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor
88be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor  template<int ...Values>
89be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor  struct square_tuple<int_tuple<Values...>> {
90be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor    typedef int_tuple<(Values*Values)...> type;
91be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor  };
92be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor
93dee196ef31073b40c48d60d9fa626ee1d8daaaeeDouglas Gregor  int check2[is_same<square_tuple<int_tuple<1, 2, -3> >::type,
94be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor                     int_tuple<1, 4, 9>>::value? 1 : -1];
95dee196ef31073b40c48d60d9fa626ee1d8daaaeeDouglas Gregor
96dee196ef31073b40c48d60d9fa626ee1d8daaaeeDouglas Gregor  template<int ...Values> struct sum;
97dee196ef31073b40c48d60d9fa626ee1d8daaaeeDouglas Gregor
98dee196ef31073b40c48d60d9fa626ee1d8daaaeeDouglas Gregor  template<int First, int ...Rest>
99dee196ef31073b40c48d60d9fa626ee1d8daaaeeDouglas Gregor  struct sum<First, Rest...> {
100dee196ef31073b40c48d60d9fa626ee1d8daaaeeDouglas Gregor    static const int value = First + sum<Rest...>::value;
101dee196ef31073b40c48d60d9fa626ee1d8daaaeeDouglas Gregor  };
102dee196ef31073b40c48d60d9fa626ee1d8daaaeeDouglas Gregor
103dee196ef31073b40c48d60d9fa626ee1d8daaaeeDouglas Gregor  template<>
104dee196ef31073b40c48d60d9fa626ee1d8daaaeeDouglas Gregor  struct sum<> {
105dee196ef31073b40c48d60d9fa626ee1d8daaaeeDouglas Gregor    static const int value = 0;
106dee196ef31073b40c48d60d9fa626ee1d8daaaeeDouglas Gregor  };
107dee196ef31073b40c48d60d9fa626ee1d8daaaeeDouglas Gregor
108dee196ef31073b40c48d60d9fa626ee1d8daaaeeDouglas Gregor  int check3[sum<1, 2, 3, 4, 5>::value == 15? 1 : -1];
10969e5aed635946419d85a6be8639260e2eb476cb1Douglas Gregor
11069e5aed635946419d85a6be8639260e2eb476cb1Douglas Gregor  template<int ... Values>
11169e5aed635946419d85a6be8639260e2eb476cb1Douglas Gregor  struct lazy_sum {
11269e5aed635946419d85a6be8639260e2eb476cb1Douglas Gregor    int operator()() {
11369e5aed635946419d85a6be8639260e2eb476cb1Douglas Gregor      return sum<Values...>::value;
11469e5aed635946419d85a6be8639260e2eb476cb1Douglas Gregor    }
11569e5aed635946419d85a6be8639260e2eb476cb1Douglas Gregor  };
11669e5aed635946419d85a6be8639260e2eb476cb1Douglas Gregor
11769e5aed635946419d85a6be8639260e2eb476cb1Douglas Gregor  void f() {
11869e5aed635946419d85a6be8639260e2eb476cb1Douglas Gregor    lazy_sum<1, 2, 3, 4, 5>()();
11969e5aed635946419d85a6be8639260e2eb476cb1Douglas Gregor  }
120be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor}
121be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor
122d53e16abd1dcaa2942d5183f48e7f63d0e75b35aDouglas Gregornamespace ListMath {
123d53e16abd1dcaa2942d5183f48e7f63d0e75b35aDouglas Gregor  template<typename T, T ... V> struct add;
124d53e16abd1dcaa2942d5183f48e7f63d0e75b35aDouglas Gregor
125d53e16abd1dcaa2942d5183f48e7f63d0e75b35aDouglas Gregor  template<typename T, T i, T ... V>
126d53e16abd1dcaa2942d5183f48e7f63d0e75b35aDouglas Gregor  struct add<T, i, V...> {
127d53e16abd1dcaa2942d5183f48e7f63d0e75b35aDouglas Gregor    static const T value = i + add<T, V...>::value;
128d53e16abd1dcaa2942d5183f48e7f63d0e75b35aDouglas Gregor  };
129d53e16abd1dcaa2942d5183f48e7f63d0e75b35aDouglas Gregor
130d53e16abd1dcaa2942d5183f48e7f63d0e75b35aDouglas Gregor  template<typename T>
131d53e16abd1dcaa2942d5183f48e7f63d0e75b35aDouglas Gregor  struct add<T> {
132d53e16abd1dcaa2942d5183f48e7f63d0e75b35aDouglas Gregor    static const T value = T();
133d53e16abd1dcaa2942d5183f48e7f63d0e75b35aDouglas Gregor  };
134d53e16abd1dcaa2942d5183f48e7f63d0e75b35aDouglas Gregor
135d53e16abd1dcaa2942d5183f48e7f63d0e75b35aDouglas Gregor  template<typename T, T ... V>
136d53e16abd1dcaa2942d5183f48e7f63d0e75b35aDouglas Gregor  struct List {
137d53e16abd1dcaa2942d5183f48e7f63d0e75b35aDouglas Gregor    struct sum {
138d53e16abd1dcaa2942d5183f48e7f63d0e75b35aDouglas Gregor      static const T value = add<T, V...>::value;
139d53e16abd1dcaa2942d5183f48e7f63d0e75b35aDouglas Gregor    };
140d53e16abd1dcaa2942d5183f48e7f63d0e75b35aDouglas Gregor  };
141d53e16abd1dcaa2942d5183f48e7f63d0e75b35aDouglas Gregor
142d53e16abd1dcaa2942d5183f48e7f63d0e75b35aDouglas Gregor  template<int ... V>
143d53e16abd1dcaa2942d5183f48e7f63d0e75b35aDouglas Gregor  struct ListI : public List<int, V...> {
144d53e16abd1dcaa2942d5183f48e7f63d0e75b35aDouglas Gregor  };
145d53e16abd1dcaa2942d5183f48e7f63d0e75b35aDouglas Gregor
146d53e16abd1dcaa2942d5183f48e7f63d0e75b35aDouglas Gregor  int check0[ListI<1, 2, 3>::sum::value == 6? 1 : -1];
147d53e16abd1dcaa2942d5183f48e7f63d0e75b35aDouglas Gregor}
148d53e16abd1dcaa2942d5183f48e7f63d0e75b35aDouglas Gregor
149be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregornamespace Indices {
150be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor  template<unsigned I, unsigned N, typename IntTuple>
151be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor  struct build_indices_impl;
152be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor
153be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor  template<unsigned I, unsigned N, int ...Indices>
154be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor  struct build_indices_impl<I, N, int_tuple<Indices...> >
155be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor    : build_indices_impl<I+1, N, int_tuple<Indices..., I> > {
156be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor  };
157be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor
158be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor  template<unsigned N, int ...Indices>
159be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor  struct build_indices_impl<N, N, int_tuple<Indices...> > {
160be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor    typedef int_tuple<Indices...> type;
161be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor  };
162be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor
163be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor  template<unsigned N>
164be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor  struct build_indices : build_indices_impl<0, N, int_tuple<> > { };
165be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor
166be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor  int check0[is_same<build_indices<5>::type,
167be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor                     int_tuple<0, 1, 2, 3, 4>>::value? 1 : -1];
168be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor}
16961c4d28e36cd3f1be392cb77f07436d1fa6b0f9fDouglas Gregor
17061c4d28e36cd3f1be392cb77f07436d1fa6b0f9fDouglas Gregornamespace TemplateTemplateApply {
17161c4d28e36cd3f1be392cb77f07436d1fa6b0f9fDouglas Gregor  template<typename T, template<class> class ...Meta>
17261c4d28e36cd3f1be392cb77f07436d1fa6b0f9fDouglas Gregor  struct apply_each {
17361c4d28e36cd3f1be392cb77f07436d1fa6b0f9fDouglas Gregor    typedef tuple<typename Meta<T>::type...> type;
17461c4d28e36cd3f1be392cb77f07436d1fa6b0f9fDouglas Gregor  };
17561c4d28e36cd3f1be392cb77f07436d1fa6b0f9fDouglas Gregor
17661c4d28e36cd3f1be392cb77f07436d1fa6b0f9fDouglas Gregor  template<typename T>
17761c4d28e36cd3f1be392cb77f07436d1fa6b0f9fDouglas Gregor  struct add_reference {
17861c4d28e36cd3f1be392cb77f07436d1fa6b0f9fDouglas Gregor    typedef T& type;
17961c4d28e36cd3f1be392cb77f07436d1fa6b0f9fDouglas Gregor  };
18061c4d28e36cd3f1be392cb77f07436d1fa6b0f9fDouglas Gregor
18161c4d28e36cd3f1be392cb77f07436d1fa6b0f9fDouglas Gregor  template<typename T>
18261c4d28e36cd3f1be392cb77f07436d1fa6b0f9fDouglas Gregor  struct add_pointer {
18361c4d28e36cd3f1be392cb77f07436d1fa6b0f9fDouglas Gregor    typedef T* type;
18461c4d28e36cd3f1be392cb77f07436d1fa6b0f9fDouglas Gregor  };
18561c4d28e36cd3f1be392cb77f07436d1fa6b0f9fDouglas Gregor
18661c4d28e36cd3f1be392cb77f07436d1fa6b0f9fDouglas Gregor  template<typename T>
18761c4d28e36cd3f1be392cb77f07436d1fa6b0f9fDouglas Gregor  struct add_const {
18861c4d28e36cd3f1be392cb77f07436d1fa6b0f9fDouglas Gregor    typedef const T type;
18961c4d28e36cd3f1be392cb77f07436d1fa6b0f9fDouglas Gregor  };
19061c4d28e36cd3f1be392cb77f07436d1fa6b0f9fDouglas Gregor
19161c4d28e36cd3f1be392cb77f07436d1fa6b0f9fDouglas Gregor  int check0[is_same<apply_each<int,
19261c4d28e36cd3f1be392cb77f07436d1fa6b0f9fDouglas Gregor                                add_reference, add_pointer, add_const>::type,
19361c4d28e36cd3f1be392cb77f07436d1fa6b0f9fDouglas Gregor                     tuple<int&, int*, int const>>::value? 1 : -1];
194a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor
195a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor  template<typename T, template<class> class ...Meta>
196a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor  struct apply_each_indirect {
197a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor    typedef typename apply_each<T, Meta...>::type type;
198a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor  };
199a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor
200a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor  int check1[is_same<apply_each_indirect<int, add_reference, add_pointer,
201a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor                                         add_const>::type,
202a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor                     tuple<int&, int*, int const>>::value? 1 : -1];
203a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor
204a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor  template<typename T, typename ...Meta>
205a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor  struct apply_each_nested {
206a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor    typedef typename apply_each<T, Meta::template apply...>::type type;
207a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor  };
208a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor
209a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor  struct add_reference_meta {
210a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor    template<typename T>
211a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor    struct apply {
212a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor      typedef T& type;
213a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor    };
214a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor  };
215a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor
216a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor  struct add_pointer_meta {
217a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor    template<typename T>
218a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor    struct apply {
219a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor      typedef T* type;
220a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor    };
221a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor  };
222a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor
223a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor  struct add_const_meta {
224a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor    template<typename T>
225a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor    struct apply {
226a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor      typedef const T type;
227a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor    };
228a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor  };
229a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor
230a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor  int check2[is_same<apply_each_nested<int, add_reference_meta,
231a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor                                       add_pointer_meta, add_const_meta>::type,
232a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor                     tuple<int&, int*, int const>>::value? 1 : -1];
233a7fc901a2e39bfe55bfcff5934b2d9fdf9656491Douglas Gregor
23461c4d28e36cd3f1be392cb77f07436d1fa6b0f9fDouglas Gregor}
235603cfb4da2f7ba08a1c3452c2fbf70585b8e7621Douglas Gregor
236603cfb4da2f7ba08a1c3452c2fbf70585b8e7621Douglas Gregornamespace FunctionTypes {
237603cfb4da2f7ba08a1c3452c2fbf70585b8e7621Douglas Gregor  template<typename FunctionType>
238603cfb4da2f7ba08a1c3452c2fbf70585b8e7621Douglas Gregor  struct Arity;
239603cfb4da2f7ba08a1c3452c2fbf70585b8e7621Douglas Gregor
240603cfb4da2f7ba08a1c3452c2fbf70585b8e7621Douglas Gregor  template<typename R, typename ...Types>
241603cfb4da2f7ba08a1c3452c2fbf70585b8e7621Douglas Gregor  struct Arity<R(Types...)> {
242603cfb4da2f7ba08a1c3452c2fbf70585b8e7621Douglas Gregor    static const unsigned value = sizeof...(Types);
243603cfb4da2f7ba08a1c3452c2fbf70585b8e7621Douglas Gregor  };
244603cfb4da2f7ba08a1c3452c2fbf70585b8e7621Douglas Gregor
245603cfb4da2f7ba08a1c3452c2fbf70585b8e7621Douglas Gregor  template<typename R, typename ...Types>
246603cfb4da2f7ba08a1c3452c2fbf70585b8e7621Douglas Gregor  struct Arity<R(Types......)> {
247603cfb4da2f7ba08a1c3452c2fbf70585b8e7621Douglas Gregor    static const unsigned value = sizeof...(Types);
248603cfb4da2f7ba08a1c3452c2fbf70585b8e7621Douglas Gregor  };
249603cfb4da2f7ba08a1c3452c2fbf70585b8e7621Douglas Gregor
250603cfb4da2f7ba08a1c3452c2fbf70585b8e7621Douglas Gregor  template<typename R, typename T1, typename T2, typename T3, typename T4>
251603cfb4da2f7ba08a1c3452c2fbf70585b8e7621Douglas Gregor  struct Arity<R(T1, T2, T3, T4)>; // expected-note{{template is declared here}}
252603cfb4da2f7ba08a1c3452c2fbf70585b8e7621Douglas Gregor
253603cfb4da2f7ba08a1c3452c2fbf70585b8e7621Douglas Gregor  int check0[Arity<int()>::value == 0? 1 : -1];
254603cfb4da2f7ba08a1c3452c2fbf70585b8e7621Douglas Gregor  int check1[Arity<int(float, double)>::value == 2? 1 : -1];
255603cfb4da2f7ba08a1c3452c2fbf70585b8e7621Douglas Gregor  int check2[Arity<int(float...)>::value == 1? 1 : -1];
256603cfb4da2f7ba08a1c3452c2fbf70585b8e7621Douglas Gregor  int check3[Arity<int(float, double, long double...)>::value == 3? 1 : -1];
257603cfb4da2f7ba08a1c3452c2fbf70585b8e7621Douglas Gregor  Arity<int(float, double, long double, char)> check4; // expected-error{{implicit instantiation of undefined template 'FunctionTypes::Arity<int (float, double, long double, char)>'}}
258603cfb4da2f7ba08a1c3452c2fbf70585b8e7621Douglas Gregor}
259a03478231363c67ea0e1f4bc1bc708e064040e56Douglas Gregor
260a03478231363c67ea0e1f4bc1bc708e064040e56Douglas Gregornamespace SuperReplace {
261a03478231363c67ea0e1f4bc1bc708e064040e56Douglas Gregor  template<typename T>
262a03478231363c67ea0e1f4bc1bc708e064040e56Douglas Gregor  struct replace_with_int {
263a03478231363c67ea0e1f4bc1bc708e064040e56Douglas Gregor    typedef int type;
264a03478231363c67ea0e1f4bc1bc708e064040e56Douglas Gregor  };
265a03478231363c67ea0e1f4bc1bc708e064040e56Douglas Gregor
266a03478231363c67ea0e1f4bc1bc708e064040e56Douglas Gregor  template<template<typename ...> class TT, typename ...Types>
267a03478231363c67ea0e1f4bc1bc708e064040e56Douglas Gregor  struct replace_with_int<TT<Types...>> {
268a03478231363c67ea0e1f4bc1bc708e064040e56Douglas Gregor    typedef TT<typename replace_with_int<Types>::type...> type;
269a03478231363c67ea0e1f4bc1bc708e064040e56Douglas Gregor  };
270a03478231363c67ea0e1f4bc1bc708e064040e56Douglas Gregor
271a03478231363c67ea0e1f4bc1bc708e064040e56Douglas Gregor  int check0[is_same<replace_with_int<pair<tuple<float, double, short>,
272a03478231363c67ea0e1f4bc1bc708e064040e56Douglas Gregor                                           pair<char, unsigned char>>>::type,
273a03478231363c67ea0e1f4bc1bc708e064040e56Douglas Gregor                     pair<tuple<int, int, int>, pair<int, int>>>::value? 1 : -1];
274a03478231363c67ea0e1f4bc1bc708e064040e56Douglas Gregor}
275