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