| 1 | // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s |
| 2 | |
| 3 | // Metafunction to extract the Nth type from a set of types. |
| 4 | template<unsigned N, typename ...Types> struct get_nth_type; |
| 5 | |
| 6 | template<unsigned N, typename Head, typename ...Tail> |
| 7 | struct get_nth_type<N, Head, Tail...> : get_nth_type<N-1, Tail...> { }; |
| 8 | |
| 9 | template<typename Head, typename ...Tail> |
| 10 | struct get_nth_type<0, Head, Tail...> { |
| 11 | typedef Head type; |
| 12 | }; |
| 13 | |
| 14 | // Placeholder type when get_nth_type fails. |
| 15 | struct no_type {}; |
| 16 | |
| 17 | template<unsigned N> |
| 18 | struct get_nth_type<N> { |
| 19 | typedef no_type type; |
| 20 | }; |
| 21 | |
| 22 | template<typename T, typename U> struct pair { }; |
| 23 | template<typename T, typename U> pair<T, U> make_pair(T, U); |
| 24 | |
| 25 | // For a function parameter pack that occurs at the end of the |
| 26 | // parameter-declaration-list, the type A of each remaining argument |
| 27 | // of the call is compared with the type P of the declarator-id of the |
| 28 | // function parameter pack. |
| 29 | template<typename ...Args> |
| 30 | typename get_nth_type<0, Args...>::type first_arg(Args...); |
| 31 | |
| 32 | template<typename ...Args> |
| 33 | typename get_nth_type<1, Args...>::type second_arg(Args...); |
| 34 | |
| 35 | void test_simple_deduction(int *ip, float *fp, double *dp) { |
| 36 | int *ip1 = first_arg(ip); |
| 37 | int *ip2 = first_arg(ip, fp); |
| 38 | int *ip3 = first_arg(ip, fp, dp); |
| 39 | no_type nt1 = first_arg(); |
| 40 | } |
| 41 | |
| 42 | template<typename ...Args> |
| 43 | typename get_nth_type<0, Args...>::type first_arg_ref(Args&...); |
| 44 | |
| 45 | template<typename ...Args> |
| 46 | typename get_nth_type<1, Args...>::type second_arg_ref(Args&...); |
| 47 | |
| 48 | void test_simple_ref_deduction(int *ip, float *fp, double *dp) { |
| 49 | int *ip1 = first_arg_ref(ip); |
| 50 | int *ip2 = first_arg_ref(ip, fp); |
| 51 | int *ip3 = first_arg_ref(ip, fp, dp); |
| 52 | no_type nt1 = first_arg_ref(); |
| 53 | } |
| 54 | |
| 55 | |
| 56 | // FIXME: Use the template parameter names in this diagnostic. |
| 57 | template<typename ...Args1, typename ...Args2> |
| 58 | typename get_nth_type<0, Args1...>::type first_arg_pair(pair<Args1, Args2>...); // expected-note{{candidate template ignored: could not match 'pair<type-parameter-0-0, type-parameter-0-1>' against 'int'}} |
| 59 | |
| 60 | template<typename ...Args1, typename ...Args2> |
| 61 | typename get_nth_type<1, Args1...>::type second_arg_pair(pair<Args1, Args2>...); |
| 62 | |
| 63 | void test_pair_deduction(int *ip, float *fp, double *dp) { |
| 64 | int *ip1 = first_arg_pair(make_pair(ip, 17)); |
| 65 | int *ip2 = first_arg_pair(make_pair(ip, 17), make_pair(fp, 17)); |
| 66 | int *ip3 = first_arg_pair(make_pair(ip, 17), make_pair(fp, 17), |
| 67 | make_pair(dp, 17)); |
| 68 | float *fp1 = second_arg_pair(make_pair(ip, 17), make_pair(fp, 17)); |
| 69 | float *fp2 = second_arg_pair(make_pair(ip, 17), make_pair(fp, 17), |
| 70 | make_pair(dp, 17)); |
| 71 | no_type nt1 = first_arg_pair(); |
| 72 | no_type nt2 = second_arg_pair(); |
| 73 | no_type nt3 = second_arg_pair(make_pair(ip, 17)); |
| 74 | |
| 75 | |
| 76 | first_arg_pair(make_pair(ip, 17), 16); // expected-error{{no matching function for call to 'first_arg_pair'}} |
| 77 | } |
| 78 | |
| 79 | // A function parameter pack not at the end of the parameter list is never |
| 80 | // deduced. We interpret this as meaning the types within it are never |
| 81 | // deduced, and thus must match explicitly-specified values. |
| 82 | template<typename ...Types> struct tuple { }; |
| 83 | |
| 84 | template<typename ...Types> |
| 85 | void pack_not_at_end(tuple<Types...>, Types... values, int); // expected-note {{<int *, double *> vs. <>}} |
| 86 | |
| 87 | void test_pack_not_at_end(tuple<int*, double*> t2) { |
| 88 | pack_not_at_end(t2, 0, 0, 0); // expected-error {{no match}} |
| 89 | // FIXME: Should the "original argument type must match deduced parameter |
| 90 | // type" rule apply here? |
| 91 | pack_not_at_end<int*, double*>(t2, 0, 0, 0); // ok |
| 92 | } |
| 93 | |