319 lines
11 KiB
C++
319 lines
11 KiB
C++
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
|
|
|
|
template<typename T, T ...Values> struct value_tuple {};
|
|
template<typename...> struct tuple { };
|
|
template<typename T, typename U> struct pair { };
|
|
|
|
template<typename T, T Value> struct value_c;
|
|
|
|
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 X0 {
|
|
template<T ...Values>
|
|
void f(value_tuple<T, Values...> * = 0);
|
|
};
|
|
|
|
void test_X0() {
|
|
X0<int>().f<1, 2, 3, 4, 5>();
|
|
}
|
|
|
|
namespace PacksAtDifferentLevels {
|
|
|
|
template<typename ...Types>
|
|
struct X {
|
|
template<typename> struct Inner {
|
|
static const unsigned value = 1;
|
|
};
|
|
|
|
template<typename ...YTypes>
|
|
struct Inner<tuple<pair<Types, YTypes>...> > {
|
|
static const unsigned value = sizeof...(Types) - sizeof...(YTypes);
|
|
};
|
|
};
|
|
|
|
int check0[X<short, int, long>::Inner<tuple<pair<short, unsigned short>,
|
|
pair<int, unsigned int>,
|
|
pair<long, unsigned long>>
|
|
>::value == 0? 1 : -1];
|
|
|
|
int check1[X<short, int>::Inner<tuple<pair<short, unsigned short>,
|
|
pair<int, unsigned int>,
|
|
pair<long, unsigned long>>
|
|
>::value == 1? 1 : -1];
|
|
|
|
template<unsigned ...Values> struct unsigned_tuple { };
|
|
template<typename ...Types>
|
|
struct X1 {
|
|
template<typename, typename> struct Inner {
|
|
static const unsigned value = 0;
|
|
};
|
|
|
|
template<typename ...YTypes>
|
|
struct Inner<tuple<pair<Types, YTypes>...>,
|
|
unsigned_tuple<sizeof(Types) + sizeof(YTypes)...>> {
|
|
static const unsigned value = 1;
|
|
};
|
|
};
|
|
|
|
int check2[X1<short, int, long>::Inner<tuple<pair<short, unsigned short>,
|
|
pair<int, unsigned int>,
|
|
pair<long, unsigned long>>,
|
|
unsigned_tuple<sizeof(short) + sizeof(unsigned short),
|
|
sizeof(int) + sizeof(unsigned int),
|
|
sizeof(long) + sizeof(unsigned long)>
|
|
>::value == 1? 1 : -1];
|
|
int check3[X1<short, int>::Inner<tuple<pair<short, unsigned short>,
|
|
pair<int, unsigned int>,
|
|
pair<long, unsigned long>>,
|
|
unsigned_tuple<sizeof(short) + sizeof(unsigned short),
|
|
sizeof(int) + sizeof(unsigned int),
|
|
sizeof(long) + sizeof(unsigned long)>
|
|
>::value == 0? 1 : -1];
|
|
|
|
template<typename ...Types>
|
|
struct X2 {
|
|
template<typename> struct Inner {
|
|
static const unsigned value = 1;
|
|
};
|
|
|
|
template<typename R, typename ...YTypes>
|
|
struct Inner<R(pair<Types, YTypes>...)> {
|
|
static const unsigned value = sizeof...(Types) - sizeof...(YTypes);
|
|
};
|
|
};
|
|
|
|
int check4[X2<short, int, long>::Inner<int(pair<short, unsigned short>,
|
|
pair<int, unsigned int>,
|
|
pair<long, unsigned long>)
|
|
>::value == 0? 1 : -1];
|
|
|
|
int check5[X2<short, int>::Inner<int(pair<short, unsigned short>,
|
|
pair<int, unsigned int>,
|
|
pair<long, unsigned long>)
|
|
>::value == 1? 1 : -1];
|
|
|
|
template<typename T, typename U>
|
|
struct some_function_object {
|
|
template<typename>
|
|
struct result_of;
|
|
};
|
|
|
|
template<template<class> class...> struct metafun_tuple { };
|
|
|
|
template<typename ...Types1>
|
|
struct X3 {
|
|
template<typename, typename> struct Inner {
|
|
static const unsigned value = 0;
|
|
};
|
|
|
|
template<typename ...Types2>
|
|
struct Inner<tuple<pair<Types1, Types2>...>,
|
|
metafun_tuple<some_function_object<Types1, Types2>::template result_of...> > {
|
|
static const unsigned value = 1;
|
|
};
|
|
};
|
|
|
|
int check6[X3<short, int, long>::Inner<tuple<pair<short, unsigned short>,
|
|
pair<int, unsigned int>,
|
|
pair<long, unsigned long>>,
|
|
metafun_tuple<
|
|
some_function_object<short, unsigned short>::result_of,
|
|
some_function_object<int, unsigned int>::result_of,
|
|
some_function_object<long, unsigned long>::result_of>
|
|
>::value == 1? 1 : -1];
|
|
int check7[X3<short, int>::Inner<tuple<pair<short, unsigned short>,
|
|
pair<int, unsigned int>,
|
|
pair<long, unsigned long>>,
|
|
metafun_tuple<
|
|
some_function_object<short, unsigned short>::result_of,
|
|
some_function_object<int, unsigned int>::result_of,
|
|
some_function_object<long, unsigned long>::result_of>
|
|
>::value == 0? 1 : -1];
|
|
|
|
template<unsigned I, unsigned J> struct unsigned_pair { };
|
|
|
|
template<unsigned ...Values1>
|
|
struct X4 {
|
|
template<typename> struct Inner {
|
|
static const unsigned value = 0;
|
|
};
|
|
|
|
template<unsigned ...Values2>
|
|
struct Inner<tuple<unsigned_pair<Values1, Values2>...>> {
|
|
static const unsigned value = 1;
|
|
};
|
|
};
|
|
|
|
int check8[X4<1, 3, 5>::Inner<tuple<unsigned_pair<1, 2>,
|
|
unsigned_pair<3, 4>,
|
|
unsigned_pair<5, 6>>
|
|
>::value == 1? 1 : -1];
|
|
int check9[X4<1, 3>::Inner<tuple<unsigned_pair<1, 2>,
|
|
unsigned_pair<3, 4>,
|
|
unsigned_pair<5, 6>>
|
|
>::value == 0? 1 : -1];
|
|
|
|
template<class> struct add_reference;
|
|
template<class> struct add_pointer;
|
|
template<class> struct add_const;
|
|
|
|
template<template<class> class ...Templates>
|
|
struct X5 {
|
|
template<typename> struct Inner {
|
|
static const unsigned value = 0;
|
|
};
|
|
|
|
template<typename ...Types>
|
|
struct Inner<tuple<Templates<Types>...>> {
|
|
static const unsigned value = 1;
|
|
};
|
|
};
|
|
|
|
int check10[X5<add_reference, add_pointer, add_const>
|
|
::Inner<tuple<add_reference<int>,
|
|
add_pointer<float>,
|
|
add_const<double>>>::value == 1? 1 : -1];
|
|
int check11[X5<add_reference, add_pointer>
|
|
::Inner<tuple<add_reference<int>,
|
|
add_pointer<float>,
|
|
add_const<double>>>::value == 0? 1 : -1];
|
|
|
|
namespace PR13811 {
|
|
constexpr int g(int n, int m) { return n * 10 + m; }
|
|
|
|
template<typename...A>
|
|
struct X6 {
|
|
template<typename...B>
|
|
constexpr auto f1(A ...a) const -> decltype(g(A(a + B())...)) { return g(A(a + B())...); }
|
|
|
|
template<typename...B>
|
|
constexpr auto f2(A ...a, B ...b) const -> decltype(g((&a)[b] ...)) { return g((&a)[b] ...); } // expected-note {{past-the-end}}
|
|
|
|
template<typename...B> struct Inner {
|
|
template<typename...C>
|
|
constexpr auto f(A ...a, B ...b, C ...c) const -> decltype(g(a+b+c...)) { return g(a+b+c...); }
|
|
};
|
|
};
|
|
struct A { constexpr operator int() const { return 2; } };
|
|
struct B { constexpr operator int() const { return 1; } };
|
|
|
|
static_assert(X6<unsigned char, int>().f1<A, B>(255, 1) == 12, "");
|
|
static_assert(X6<int, int>().f2(3, 4, 0, 0) == 34, "");
|
|
static_assert(X6<int, int>().f2(3, 4, 0, 1) == 34, ""); // expected-error {{constant expression}} expected-note {{in call}}
|
|
static_assert(X6<int, int>::Inner<int, int>().f(1, 2, 3, 4, 5, 6) == 102, "");
|
|
}
|
|
}
|
|
|
|
namespace ExpandingNonTypeTemplateParameters {
|
|
template<typename ...Types>
|
|
struct tuple_of_values {
|
|
template<Types ...Values> // expected-error{{a non-type template parameter cannot have type 'float'}} \
|
|
// expected-note{{template parameter is declared here}}
|
|
struct apply { // expected-note 2{{template is declared here}}
|
|
typedef tuple<value_c<Types, Values>...> type;
|
|
};
|
|
};
|
|
|
|
int i;
|
|
float f;
|
|
int check_tuple_of_values_1[
|
|
is_same<tuple_of_values<int&, float&, char, int>::apply<i, f, 'a', 17>
|
|
::type,
|
|
tuple<value_c<int&, i>, value_c<float&, f>, value_c<char, 'a'>,
|
|
value_c<int, 17>>
|
|
>::value? 1 : -1];
|
|
|
|
tuple_of_values<int, float> tv1; // expected-note{{in instantiation of template class 'ExpandingNonTypeTemplateParameters::tuple_of_values<int, float>' requested here}}
|
|
|
|
tuple_of_values<int&, float&>::apply<i, i>::type tv2; // expected-error{{non-type template parameter of reference type 'float &' cannot bind to template argument of type 'int'}}
|
|
|
|
tuple_of_values<int&, float&>::apply<i>::type tv3; // expected-error{{too few template arguments for class template 'apply'}}
|
|
|
|
tuple_of_values<int&, float&>::apply<i, f, i>::type tv4; // expected-error{{too many template arguments for class template 'apply'}}
|
|
}
|
|
|
|
namespace ExpandingFunctionParameters {
|
|
template<typename ...T>
|
|
struct X0 {
|
|
typedef int type;
|
|
};
|
|
|
|
template<typename ...T>
|
|
struct X1 {
|
|
template<typename ... U>
|
|
typename X0<T(T, U...)...>::type f(U...);
|
|
};
|
|
|
|
void test() {
|
|
X1<float> x1;
|
|
x1.f(17, 3.14159);
|
|
}
|
|
}
|
|
|
|
namespace PR10230 {
|
|
template<typename>
|
|
struct s
|
|
{
|
|
template<typename... Args>
|
|
auto f() -> int(&)[sizeof...(Args)];
|
|
};
|
|
|
|
void main()
|
|
{
|
|
int (&ir1)[1] = s<int>().f<int>();
|
|
int (&ir3)[3] = s<int>().f<int, float, double>();
|
|
}
|
|
}
|
|
|
|
namespace PR13386 {
|
|
template<typename...> struct tuple {};
|
|
template<typename...T>
|
|
struct S {
|
|
template<typename...U>
|
|
void f(T &&...t, U &&...u) {} // expected-note {{candidate}}
|
|
template<typename...U>
|
|
void g(U &&...u, T &&...t) {} // expected-note {{candidate}}
|
|
template<typename...U>
|
|
void h(tuple<T, U> &&...) {} // expected-note 2{{candidate}}
|
|
|
|
template<typename...U>
|
|
struct X {
|
|
template<typename...V>
|
|
void x(tuple<T, U, V> &&...); // expected-error {{different lengths}}
|
|
};
|
|
};
|
|
|
|
void test() {
|
|
S<>().f();
|
|
S<>().f(0);
|
|
S<int>().f(0);
|
|
S<int>().f(0, 1);
|
|
S<int, int>().f(0); // expected-error {{no matching member function for call}}
|
|
|
|
S<>().g();
|
|
S<>().g(0);
|
|
S<int>().g(0);
|
|
S<int>().g(0, 1); // expected-error {{no matching member function for call}}
|
|
S<int>().g<int>(0, 1);
|
|
S<int, int>().g(0, 1);
|
|
|
|
S<>().h();
|
|
S<>().h(0); // expected-error {{no matching member function for call}}
|
|
S<int>().h({}); // expected-error {{no matching member function for call}}
|
|
S<int>().h<int>({});
|
|
S<int>().h(tuple<int,int>{});
|
|
S<int, int>().h(tuple<int,int>{}, tuple<int,int>{});
|
|
|
|
S<int, int>::X<char>(); // expected-note {{here}}
|
|
}
|
|
}
|