// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s // This is a collection of various template metafunctions involving // variadic templates, which are meant to exercise common use cases. template struct is_same { static const bool value = false; }; template struct is_same { static const bool value = true; }; template struct tuple { }; template struct int_tuple { }; template struct pair { }; namespace Count { template struct count { static const unsigned value = 1 + count::value; }; template struct count { static const unsigned value = 1; }; int check1[count::value == 1? 1 : -1]; int check2[count::value == 2? 1 : -1]; int check3[count::value == 3? 1 : -1]; } namespace CountWithPackExpansion { template struct count; template struct count { static const unsigned value = 1 + count::value; }; template<> struct count<> { static const unsigned value = 0; }; int check0[count<>::value == 0? 1 : -1]; int check1[count::value == 1? 1 : -1]; int check2[count::value == 2? 1 : -1]; int check3[count::value == 3? 1 : -1]; } namespace Replace { // Simple metafunction that replaces the template arguments of // template template parameters with 'int'. template struct EverythingToInt; template class TT, typename T1, typename T2> struct EverythingToInt > { typedef TT type; }; int check0[is_same>::type, tuple>::value? 1 : -1]; } namespace Math { template struct double_values { typedef int_tuple type; }; int check0[is_same::type, int_tuple<2, 4, -6>>::value? 1 : -1]; template struct square { typedef int_tuple<(Values*Values)...> type; }; int check1[is_same::type, int_tuple<1, 4, 9>>::value? 1 : -1]; template struct square_tuple; template struct square_tuple> { typedef int_tuple<(Values*Values)...> type; }; int check2[is_same >::type, int_tuple<1, 4, 9>>::value? 1 : -1]; template struct sum; template struct sum { static const int value = First + sum::value; }; template<> struct sum<> { static const int value = 0; }; int check3[sum<1, 2, 3, 4, 5>::value == 15? 1 : -1]; template struct lazy_sum { int operator()() { return sum::value; } }; void f() { lazy_sum<1, 2, 3, 4, 5>()(); } } namespace ListMath { template struct add; template struct add { static const T value = i + add::value; }; template struct add { static const T value = T(); }; template struct List { struct sum { static const T value = add::value; }; }; template struct ListI : public List { }; int check0[ListI<1, 2, 3>::sum::value == 6? 1 : -1]; } namespace Indices { template struct build_indices_impl; template struct build_indices_impl > : build_indices_impl > { }; template struct build_indices_impl > { typedef int_tuple type; }; template struct build_indices : build_indices_impl<0, N, int_tuple<> > { }; int check0[is_same::type, int_tuple<0, 1, 2, 3, 4>>::value? 1 : -1]; } namespace TemplateTemplateApply { template class ...Meta> struct apply_each { typedef tuple::type...> type; }; template struct add_reference { typedef T& type; }; template struct add_pointer { typedef T* type; }; template struct add_const { typedef const T type; }; int check0[is_same::type, tuple>::value? 1 : -1]; template class ...Meta> struct apply_each_indirect { typedef typename apply_each::type type; }; int check1[is_same::type, tuple>::value? 1 : -1]; template struct apply_each_nested { typedef typename apply_each::type type; }; struct add_reference_meta { template struct apply { typedef T& type; }; }; struct add_pointer_meta { template struct apply { typedef T* type; }; }; struct add_const_meta { template struct apply { typedef const T type; }; }; int check2[is_same::type, tuple>::value? 1 : -1]; } namespace FunctionTypes { template struct Arity; template struct Arity { static const unsigned value = sizeof...(Types); }; template struct Arity { // expected-warning {{varargs}} expected-note {{pack}} expected-note {{insert ','}} static const unsigned value = sizeof...(Types); }; template struct Arity; // expected-note{{template is declared here}} int check0[Arity::value == 0? 1 : -1]; int check1[Arity::value == 2? 1 : -1]; int check2[Arity::value == 1? 1 : -1]; int check3[Arity::value == 3? 1 : -1]; Arity check4; // expected-error{{implicit instantiation of undefined template 'FunctionTypes::Arity'}} } namespace SuperReplace { template struct replace_with_int { typedef int type; }; template class TT, typename ...Types> struct replace_with_int> { typedef TT::type...> type; }; int check0[is_same, pair>>::type, pair, pair>>::value? 1 : -1]; }