| Douglas Gregor | 603d81b | 2010-07-13 08:18:22 +0000 | [diff] [blame] | 1 | // RUN: %clang_cc1 -fsyntax-only -verify %s | 
| Douglas Gregor | adee3e3 | 2009-11-11 23:06:43 +0000 | [diff] [blame] | 2 |  | 
|  | 3 | // Template argument deduction with template template parameters. | 
|  | 4 | template<typename T, template<T> class A> | 
|  | 5 | struct X0 { | 
|  | 6 | static const unsigned value = 0; | 
|  | 7 | }; | 
|  | 8 |  | 
|  | 9 | template<template<int> class A> | 
|  | 10 | struct X0<int, A> { | 
|  | 11 | static const unsigned value = 1; | 
|  | 12 | }; | 
|  | 13 |  | 
|  | 14 | template<int> struct X0i; | 
|  | 15 | template<long> struct X0l; | 
|  | 16 | int array_x0a[X0<long, X0l>::value == 0? 1 : -1]; | 
|  | 17 | int array_x0b[X0<int, X0i>::value == 1? 1 : -1]; | 
|  | 18 |  | 
|  | 19 | template<typename T, typename U> | 
|  | 20 | struct is_same { | 
|  | 21 | static const bool value = false; | 
|  | 22 | }; | 
|  | 23 |  | 
|  | 24 | template<typename T> | 
|  | 25 | struct is_same<T, T> { | 
|  | 26 | static const bool value = true; | 
|  | 27 | }; | 
|  | 28 |  | 
|  | 29 | template<typename T> struct allocator { }; | 
|  | 30 | template<typename T, typename Alloc = allocator<T> > struct vector {}; | 
|  | 31 |  | 
|  | 32 | // Fun with meta-lambdas! | 
|  | 33 | struct _1 {}; | 
|  | 34 | struct _2 {}; | 
|  | 35 |  | 
|  | 36 | // Replaces all occurrences of _1 with Arg1 and _2 with Arg2 in T. | 
|  | 37 | template<typename T, typename Arg1, typename Arg2> | 
|  | 38 | struct Replace { | 
|  | 39 | typedef T type; | 
|  | 40 | }; | 
|  | 41 |  | 
|  | 42 | // Replacement of the whole type. | 
|  | 43 | template<typename Arg1, typename Arg2> | 
|  | 44 | struct Replace<_1, Arg1, Arg2> { | 
|  | 45 | typedef Arg1 type; | 
|  | 46 | }; | 
|  | 47 |  | 
|  | 48 | template<typename Arg1, typename Arg2> | 
|  | 49 | struct Replace<_2, Arg1, Arg2> { | 
|  | 50 | typedef Arg2 type; | 
|  | 51 | }; | 
|  | 52 |  | 
|  | 53 | // Replacement through cv-qualifiers | 
|  | 54 | template<typename T, typename Arg1, typename Arg2> | 
|  | 55 | struct Replace<const T, Arg1, Arg2> { | 
|  | 56 | typedef typename Replace<T, Arg1, Arg2>::type const type; | 
|  | 57 | }; | 
|  | 58 |  | 
|  | 59 | // Replacement of templates | 
|  | 60 | template<template<typename> class TT, typename T1, typename Arg1, typename Arg2> | 
|  | 61 | struct Replace<TT<T1>, Arg1, Arg2> { | 
|  | 62 | typedef TT<typename Replace<T1, Arg1, Arg2>::type> type; | 
|  | 63 | }; | 
|  | 64 |  | 
|  | 65 | template<template<typename, typename> class TT, typename T1, typename T2, | 
|  | 66 | typename Arg1, typename Arg2> | 
|  | 67 | struct Replace<TT<T1, T2>, Arg1, Arg2> { | 
|  | 68 | typedef TT<typename Replace<T1, Arg1, Arg2>::type, | 
|  | 69 | typename Replace<T2, Arg1, Arg2>::type> type; | 
|  | 70 | }; | 
|  | 71 |  | 
|  | 72 | // Just for kicks... | 
|  | 73 | template<template<typename, typename> class TT, typename T1, | 
|  | 74 | typename Arg1, typename Arg2> | 
|  | 75 | struct Replace<TT<T1, _2>, Arg1, Arg2> { | 
|  | 76 | typedef TT<typename Replace<T1, Arg1, Arg2>::type, Arg2> type; | 
|  | 77 | }; | 
|  | 78 |  | 
|  | 79 | int array0[is_same<Replace<_1, int, float>::type, int>::value? 1 : -1]; | 
|  | 80 | int array1[is_same<Replace<const _1, int, float>::type, const int>::value? 1 : -1]; | 
|  | 81 | int array2[is_same<Replace<vector<_1>, int, float>::type, vector<int> >::value? 1 : -1]; | 
|  | 82 | int array3[is_same<Replace<vector<const _1>, int, float>::type, vector<const int> >::value? 1 : -1]; | 
|  | 83 | int array4[is_same<Replace<vector<int, _2>, double, float>::type, vector<int, float> >::value? 1 : -1]; | 
| Chandler Carruth | c712ce1 | 2009-12-30 04:10:01 +0000 | [diff] [blame] | 84 |  | 
|  | 85 | // PR5911 | 
|  | 86 | template <typename T, int N> void f(const T (&a)[N]); | 
|  | 87 | int iarr[] = { 1 }; | 
|  | 88 | void test_PR5911() { f(iarr); } | 
| Chandler Carruth | c126311 | 2010-02-07 21:33:28 +0000 | [diff] [blame] | 89 |  | 
|  | 90 | // Must not examine base classes of incomplete type during template argument | 
|  | 91 | // deduction. | 
|  | 92 | namespace PR6257 { | 
|  | 93 | template <typename T> struct X { | 
|  | 94 | template <typename U> X(const X<U>& u); | 
|  | 95 | }; | 
|  | 96 | struct A; | 
|  | 97 | void f(A& a); | 
|  | 98 | void f(const X<A>& a); | 
|  | 99 | void test(A& a) { (void)f(a); } | 
|  | 100 | } | 
| Douglas Gregor | 603d81b | 2010-07-13 08:18:22 +0000 | [diff] [blame] | 101 |  | 
|  | 102 | // PR7463 | 
|  | 103 | namespace PR7463 { | 
| Chandler Carruth | cb3b5a4 | 2010-07-14 06:36:18 +0000 | [diff] [blame] | 104 | const int f (); | 
| Douglas Gregor | 603d81b | 2010-07-13 08:18:22 +0000 | [diff] [blame] | 105 | template <typename T_> void g (T_&); // expected-note{{T_ = int}} | 
|  | 106 | void h (void) { g(f()); } // expected-error{{no matching function for call}} | 
|  | 107 | } | 
| John McCall | 42d7d19 | 2010-08-05 09:05:08 +0000 | [diff] [blame] | 108 |  | 
|  | 109 | namespace test0 { | 
| Douglas Gregor | b0f2ea9 | 2011-02-17 06:52:25 +0000 | [diff] [blame] | 110 | template <class T> void make(const T *(*fn)()); // expected-note {{candidate template ignored: can't deduce a type for 'T' which would make 'const T' equal 'char'}} | 
| John McCall | 42d7d19 | 2010-08-05 09:05:08 +0000 | [diff] [blame] | 111 | char *char_maker(); | 
|  | 112 | void test() { | 
|  | 113 | make(char_maker); // expected-error {{no matching function for call to 'make'}} | 
|  | 114 | } | 
|  | 115 | } | 
| John McCall | f733268 | 2010-08-19 00:20:19 +0000 | [diff] [blame] | 116 |  | 
|  | 117 | namespace test1 { | 
|  | 118 | template<typename T> void foo(const T a[3][3]); | 
|  | 119 | void test() { | 
|  | 120 | int a[3][3]; | 
|  | 121 | foo(a); | 
|  | 122 | } | 
|  | 123 | } | 
| John McCall | 0856906 | 2010-08-28 22:14:41 +0000 | [diff] [blame] | 124 |  | 
|  | 125 | // PR7708 | 
|  | 126 | namespace test2 { | 
|  | 127 | template<typename T> struct Const { typedef void const type; }; | 
|  | 128 |  | 
|  | 129 | template<typename T> void f(T, typename Const<T>::type*); | 
|  | 130 | template<typename T> void f(T, void const *); | 
|  | 131 |  | 
|  | 132 | void test() { | 
|  | 133 | void *p = 0; | 
|  | 134 | f(0, p); | 
|  | 135 | } | 
|  | 136 | } | 
| John McCall | 036855a | 2010-10-12 19:40:14 +0000 | [diff] [blame] | 137 |  | 
|  | 138 | // rdar://problem/8537391 | 
|  | 139 | namespace test3 { | 
|  | 140 | struct Foo { | 
|  | 141 | template <void F(char)> static inline void foo(); | 
|  | 142 | }; | 
|  | 143 |  | 
|  | 144 | class Bar { | 
|  | 145 | template<typename T> static inline void wobble(T ch); | 
|  | 146 |  | 
|  | 147 | public: | 
|  | 148 | static void madness() { | 
|  | 149 | Foo::foo<wobble<char> >(); | 
|  | 150 | } | 
|  | 151 | }; | 
|  | 152 | } | 
| John McCall | 6730e4d | 2011-07-15 07:47:58 +0000 | [diff] [blame^] | 153 |  | 
|  | 154 | // Verify that we can deduce enum-typed arguments correctly. | 
|  | 155 | namespace test14 { | 
|  | 156 | enum E { E0, E1 }; | 
|  | 157 | template <E> struct A {}; | 
|  | 158 | template <E e> void foo(const A<e> &a) {} | 
|  | 159 |  | 
|  | 160 | void test() { | 
|  | 161 | A<E0> a; | 
|  | 162 | foo(a); | 
|  | 163 | } | 
|  | 164 | } |