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