| 1 | // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s |
| 2 | // expected-no-diagnostics |
| 3 | |
| 4 | // Metafunction to extract the Nth type from a set of types. |
| 5 | template<unsigned N, typename ...Types> struct get_nth_type; |
| 6 | |
| 7 | template<unsigned N, typename Head, typename ...Tail> |
| 8 | struct get_nth_type<N, Head, Tail...> : get_nth_type<N-1, Tail...> { }; |
| 9 | |
| 10 | template<typename Head, typename ...Tail> |
| 11 | struct get_nth_type<0, Head, Tail...> { |
| 12 | typedef Head type; |
| 13 | }; |
| 14 | |
| 15 | // Placeholder type when get_nth_type fails. |
| 16 | struct no_type {}; |
| 17 | |
| 18 | template<unsigned N> |
| 19 | struct get_nth_type<N> { |
| 20 | typedef no_type type; |
| 21 | }; |
| 22 | |
| 23 | template<typename ...Args> |
| 24 | typename get_nth_type<0, Args...>::type first_arg(Args...); |
| 25 | |
| 26 | template<typename ...Args> |
| 27 | typename get_nth_type<1, Args...>::type second_arg(Args...); |
| 28 | |
| 29 | // Test explicit specification of function template arguments. |
| 30 | void test_explicit_spec_simple() { |
| 31 | int *ip1 = first_arg<int *>(0); |
| 32 | int *ip2 = first_arg<int *, float*>(0, 0); |
| 33 | float *fp1 = first_arg<float *, double*, int*>(0, 0, 0); |
| 34 | } |
| 35 | |
| 36 | // Template argument deduction can extend the sequence of template |
| 37 | // arguments corresponding to a template parameter pack, even when the |
| 38 | // sequence contains explicitly specified template arguments. |
| 39 | void test_explicit_spec_extension(double *dp) { |
| 40 | int *ip1 = first_arg<int *>(0, 0); |
| 41 | int *ip2 = first_arg<int *, float*>(0, 0, 0, 0); |
| 42 | float *fp1 = first_arg<float *, double*, int*>(0, 0, 0); |
| 43 | int *i1 = second_arg<float *>(0, (int*)0, 0); |
| 44 | double *dp1 = first_arg<>(dp); |
| 45 | } |
| 46 | |
| 47 | template<typename ...Types> |
| 48 | struct tuple { }; |
| 49 | |
| 50 | template<typename ...Types> |
| 51 | void accept_tuple(tuple<Types...>); |
| 52 | |
| 53 | void test_explicit_spec_extension_targs(tuple<int, float, double> t3) { |
| 54 | accept_tuple(t3); |
| 55 | accept_tuple<int, float, double>(t3); |
| 56 | accept_tuple<int>(t3); |
| 57 | accept_tuple<int, float>(t3); |
| 58 | } |
| 59 | |
| 60 | template<typename R, typename ...ParmTypes> |
| 61 | void accept_function_ptr(R(*)(ParmTypes...)); |
| 62 | |
| 63 | void test_explicit_spec_extension_funcparms(int (*f3)(int, float, double)) { |
| 64 | accept_function_ptr(f3); |
| 65 | accept_function_ptr<int>(f3); |
| 66 | accept_function_ptr<int, int>(f3); |
| 67 | accept_function_ptr<int, int, float>(f3); |
| 68 | accept_function_ptr<int, int, float, double>(f3); |
| 69 | } |
| 70 | |