165 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			165 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // 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);
 | |
|   }
 | |
| }
 | 
