forked from OSchip/llvm-project
267 lines
6.6 KiB
C++
267 lines
6.6 KiB
C++
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11
|
|
|
|
// 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: cannot deduce a type for 'T' that 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);
|
|
}
|
|
}
|
|
|
|
namespace PR21536 {
|
|
template<typename ...T> struct X;
|
|
template<typename A, typename ...B> struct S {
|
|
static_assert(sizeof...(B) == 1, "");
|
|
void f() {
|
|
using T = A;
|
|
using T = int;
|
|
|
|
using U = X<B...>;
|
|
using U = X<int>;
|
|
}
|
|
};
|
|
template<typename ...T> void f(S<T...>);
|
|
void g() { f(S<int, int>()); }
|
|
}
|
|
|
|
namespace PR19372 {
|
|
template <template<typename...> class C, typename ...Us> struct BindBack {
|
|
template <typename ...Ts> using apply = C<Ts..., Us...>;
|
|
};
|
|
template <typename, typename...> struct Y;
|
|
template <typename ...Ts> using Z = Y<Ts...>;
|
|
|
|
using T = BindBack<Z, int>::apply<>;
|
|
using T = Z<int>;
|
|
|
|
using U = BindBack<Z, int, int>::apply<char>;
|
|
using U = Z<char, int, int>;
|
|
|
|
namespace BetterReduction {
|
|
template<typename ...> struct S;
|
|
template<typename ...A> using X = S<A...>; // expected-note {{parameter}}
|
|
template<typename ...A> using Y = X<A..., A...>;
|
|
template<typename ...A> using Z = X<A..., 1, 2, 3>; // expected-error {{must be a type}}
|
|
|
|
using T = Y<int>;
|
|
using T = S<int, int>;
|
|
}
|
|
}
|
|
|
|
namespace PR18645 {
|
|
template<typename F> F Quux(F &&f);
|
|
auto Baz = Quux(Quux<float>);
|
|
}
|
|
|
|
namespace NonDeducedNestedNameSpecifier {
|
|
template<typename T> struct A {
|
|
template<typename U> struct B {
|
|
B(int) {}
|
|
};
|
|
};
|
|
|
|
template<typename T> int f(A<T>, typename A<T>::template B<T>);
|
|
int k = f(A<int>(), 0);
|
|
}
|
|
|
|
namespace PR27601_RecursivelyInheritedBaseSpecializationsDeductionAmbiguity {
|
|
namespace ns1 {
|
|
|
|
template<class...> struct B { };
|
|
template<class H, class ... Ts> struct B<H, Ts...> : B<> { };
|
|
template<class ... Ts> struct D : B<Ts...> { };
|
|
|
|
template<class T, class ... Ts> void f(B<T, Ts...> &) { }
|
|
|
|
int main() {
|
|
D<int, char> d;
|
|
f<int>(d);
|
|
}
|
|
} //end ns1
|
|
|
|
namespace ns2 {
|
|
|
|
template <int i, typename... Es> struct tup_impl;
|
|
|
|
template <int i> struct tup_impl<i> {}; // empty tail
|
|
|
|
template <int i, typename Head, typename... Tail>
|
|
struct tup_impl<i, Head, Tail...> : tup_impl<i + 1, Tail...> {
|
|
using value_type = Head;
|
|
Head head;
|
|
};
|
|
|
|
template <typename... Es> struct tup : tup_impl<0, Es...> {};
|
|
|
|
template <typename Head, int i, typename... Tail>
|
|
Head &get_helper(tup_impl<i, Head, Tail...> &t) {
|
|
return t.head;
|
|
}
|
|
|
|
template <typename Head, int i, typename... Tail>
|
|
Head const &get_helper(tup_impl<i, Head, Tail...> const &t) {
|
|
return t.head;
|
|
}
|
|
|
|
int main() {
|
|
tup<int, double, char> t;
|
|
get_helper<double>(t);
|
|
return 0;
|
|
}
|
|
} // end ns2
|
|
} |