forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			283 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			283 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			C++
		
	
	
	
| // RUN: %clang_cc1 -std=c++1z -verify %s
 | |
| 
 | |
| namespace std {
 | |
|   using size_t = decltype(sizeof(0));
 | |
|   template<typename T> struct initializer_list {
 | |
|     const T *p;
 | |
|     size_t n;
 | |
|     initializer_list();
 | |
|   };
 | |
|   // FIXME: This should probably not be necessary.
 | |
|   template<typename T> initializer_list(initializer_list<T>) -> initializer_list<T>;
 | |
| }
 | |
| 
 | |
| template<typename T> constexpr bool has_type(...) { return false; }
 | |
| template<typename T> constexpr bool has_type(T) { return true; }
 | |
| 
 | |
| std::initializer_list il = {1, 2, 3, 4, 5};
 | |
| 
 | |
| template<typename T> struct vector {
 | |
|   template<typename Iter> vector(Iter, Iter);
 | |
|   vector(std::initializer_list<T>);
 | |
| };
 | |
| 
 | |
| template<typename T> vector(std::initializer_list<T>) -> vector<T>;
 | |
| template<typename Iter> explicit vector(Iter, Iter) -> vector<typename Iter::value_type>;
 | |
| template<typename T> explicit vector(std::size_t, T) -> vector<T>;
 | |
| 
 | |
| vector v1 = {1, 2, 3, 4};
 | |
| static_assert(has_type<vector<int>>(v1));
 | |
| 
 | |
| struct iter { typedef char value_type; } it, end;
 | |
| vector v2(it, end);
 | |
| static_assert(has_type<vector<char>>(v2));
 | |
| 
 | |
| vector v3(5, 5);
 | |
| static_assert(has_type<vector<int>>(v3));
 | |
| 
 | |
| vector v4 = {it, end};
 | |
| static_assert(has_type<vector<iter>>(v4));
 | |
| 
 | |
| vector v5{it, end};
 | |
| static_assert(has_type<vector<iter>>(v5));
 | |
| 
 | |
| template<typename ...T> struct tuple { tuple(T...); };
 | |
| template<typename ...T> explicit tuple(T ...t) -> tuple<T...>; // expected-note {{declared}}
 | |
| // FIXME: Remove
 | |
| template<typename ...T> tuple(tuple<T...>) -> tuple<T...>;
 | |
| 
 | |
| const int n = 4;
 | |
| tuple ta = tuple{1, 'a', "foo", n};
 | |
| static_assert(has_type<tuple<int, char, const char*, int>>(ta));
 | |
| 
 | |
| tuple tb{ta};
 | |
| static_assert(has_type<tuple<int, char, const char*, int>>(tb));
 | |
| 
 | |
| // FIXME: This should be tuple<tuple<...>>; when the above guide is removed.
 | |
| tuple tc = {ta};
 | |
| static_assert(has_type<tuple<int, char, const char*, int>>(tc));
 | |
| 
 | |
| tuple td = {1, 2, 3}; // expected-error {{selected an explicit deduction guide}}
 | |
| static_assert(has_type<tuple<int, char, const char*, int>>(td));
 | |
| 
 | |
| // FIXME: This is a GCC extension for now; if CWG don't allow this, at least
 | |
| // add a warning for it.
 | |
| namespace new_expr {
 | |
|   tuple<int> *p = new tuple{0};
 | |
|   tuple<float, float> *q = new tuple(1.0f, 2.0f);
 | |
| }
 | |
| 
 | |
| namespace ambiguity {
 | |
|   template<typename T> struct A {};
 | |
|   A(unsigned short) -> A<int>; // expected-note {{candidate}}
 | |
|   A(short) -> A<int>; // expected-note {{candidate}}
 | |
|   A a = 0; // expected-error {{ambiguous deduction for template arguments of 'A'}}
 | |
| 
 | |
|   template<typename T> struct B {};
 | |
|   template<typename T> B(T(&)(int)) -> B<int>; // expected-note {{candidate function [with T = int]}}
 | |
|   template<typename T> B(int(&)(T)) -> B<int>; // expected-note {{candidate function [with T = int]}}
 | |
|   int f(int);
 | |
|   B b = f; // expected-error {{ambiguous deduction for template arguments of 'B'}}
 | |
| }
 | |
| 
 | |
| // FIXME: Revisit this once CWG decides if attributes, and [[deprecated]] in
 | |
| // particular, should be permitted here.
 | |
| namespace deprecated {
 | |
|   template<typename T> struct A { A(int); };
 | |
|   [[deprecated]] A(int) -> A<void>; // expected-note {{marked deprecated here}}
 | |
|   A a = 0; // expected-warning {{'<deduction guide for A>' is deprecated}}
 | |
| }
 | |
| 
 | |
| namespace dependent {
 | |
|   template<template<typename...> typename A> decltype(auto) a = A{1, 2, 3};
 | |
|   static_assert(has_type<vector<int>>(a<vector>));
 | |
|   static_assert(has_type<tuple<int, int, int>>(a<tuple>));
 | |
| 
 | |
|   struct B {
 | |
|     template<typename T> struct X { X(T); };
 | |
|     X(int) -> X<int>;
 | |
|     template<typename T> using Y = X<T>; // expected-note {{template}}
 | |
|   };
 | |
|   template<typename T> void f() {
 | |
|     typename T::X tx = 0;
 | |
|     typename T::Y ty = 0; // expected-error {{alias template 'Y' requires template arguments; argument deduction only allowed for class templates}}
 | |
|   }
 | |
|   template void f<B>(); // expected-note {{in instantiation of}}
 | |
| 
 | |
|   template<typename T> struct C { C(T); };
 | |
|   template<typename T> C(T) -> C<T>;
 | |
|   template<typename T> void g(T a) {
 | |
|     C b = 0;
 | |
|     C c = a;
 | |
|     using U = decltype(b); // expected-note {{previous}}
 | |
|     using U = decltype(c); // expected-error {{different types ('C<const char *>' vs 'C<int>')}}
 | |
|   }
 | |
|   void h() {
 | |
|     g(0);
 | |
|     g("foo"); // expected-note {{instantiation of}}
 | |
|   }
 | |
| }
 | |
| 
 | |
| namespace look_into_current_instantiation {
 | |
|   template<typename U> struct Q {};
 | |
|   template<typename T> struct A {
 | |
|     using U = T;
 | |
|     template<typename> using V = Q<A<T>::U>;
 | |
|     template<typename W = int> A(V<W>);
 | |
|   };
 | |
|   A a = Q<float>(); // ok, can look through class-scope typedefs and alias
 | |
|                     // templates, and members of the current instantiation
 | |
|   A<float> &r = a;
 | |
| 
 | |
|   template<typename T> struct B { // expected-note {{could not match 'B<T>' against 'int'}}
 | |
|     struct X {
 | |
|       typedef T type;
 | |
|     };
 | |
|     B(typename X::type); // expected-note {{couldn't infer template argument 'T'}}
 | |
|   };
 | |
|   B b = 0; // expected-error {{no viable}}
 | |
| 
 | |
|   // We should have a substitution failure in the immediate context of
 | |
|   // deduction when using the C(T, U) constructor (probably; core wording
 | |
|   // unclear).
 | |
|   template<typename T> struct C {
 | |
|     using U = typename T::type;
 | |
|     C(T, U);
 | |
|   };
 | |
| 
 | |
|   struct R { R(int); typedef R type; };
 | |
|   C(...) -> C<R>;
 | |
| 
 | |
|   C c = {1, 2};
 | |
| }
 | |
| 
 | |
| namespace nondeducible {
 | |
|   template<typename A, typename B> struct X {};
 | |
| 
 | |
|   template<typename A> // expected-note {{non-deducible template parameter 'A'}}
 | |
|   X() -> X<A, int>; // expected-error {{deduction guide template contains a template parameter that cannot be deduced}}
 | |
| 
 | |
|   template<typename A> // expected-note {{non-deducible template parameter 'A'}}
 | |
|   X(typename X<A, int>::type) -> X<A, int>; // expected-error {{deduction guide template contains a template parameter that cannot be deduced}}
 | |
| 
 | |
|   template<typename A = int,
 | |
|            typename B> // expected-note {{non-deducible template parameter 'B'}}
 | |
|   X(int) -> X<A, B>; // expected-error {{deduction guide template contains a template parameter that cannot be deduced}}
 | |
| 
 | |
|   template<typename A = int,
 | |
|            typename ...B>
 | |
|   X(float) -> X<A, B...>; // ok
 | |
| }
 | |
| 
 | |
| namespace default_args_from_ctor {
 | |
|   template <class A> struct S { S(A = 0) {} };
 | |
|   S s(0);
 | |
| 
 | |
|   template <class A> struct T { template<typename B> T(A = 0, B = 0) {} };
 | |
|   T t(0, 0);
 | |
| }
 | |
| 
 | |
| namespace transform_params {
 | |
|   template<typename T, T N, template<T (*v)[N]> typename U, T (*X)[N]>
 | |
|   struct A {
 | |
|     template<typename V, V M, V (*Y)[M], template<V (*v)[M]> typename W>
 | |
|     A(U<X>, W<Y>);
 | |
| 
 | |
|     static constexpr T v = N;
 | |
|   };
 | |
| 
 | |
|   int n[12];
 | |
|   template<int (*)[12]> struct Q {};
 | |
|   Q<&n> qn;
 | |
|   A a(qn, qn);
 | |
|   static_assert(a.v == 12);
 | |
| 
 | |
|   template<typename ...T> struct B {
 | |
|     template<T ...V> B(const T (&...p)[V]) {
 | |
|       constexpr int Vs[] = {V...};
 | |
|       static_assert(Vs[0] == 3 && Vs[1] == 4 && Vs[2] == 4);
 | |
|     }
 | |
|     static constexpr int (*p)(T...) = (int(*)(int, char, char))nullptr;
 | |
|   };
 | |
|   B b({1, 2, 3}, "foo", {'x', 'y', 'z', 'w'}); // ok
 | |
| 
 | |
|   template<typename ...T> struct C {
 | |
|     template<T ...V, template<T...> typename X>
 | |
|       C(X<V...>);
 | |
|   };
 | |
|   template<int...> struct Y {};
 | |
|   C c(Y<0, 1, 2>{});
 | |
| 
 | |
|   template<typename ...T> struct D {
 | |
|     template<T ...V> D(Y<V...>);
 | |
|   };
 | |
|   D d(Y<0, 1, 2>{});
 | |
| }
 | |
| 
 | |
| namespace variadic {
 | |
|   int arr3[3], arr4[4];
 | |
| 
 | |
|   // PR32673
 | |
|   template<typename T> struct A {
 | |
|     template<typename ...U> A(T, U...);
 | |
|   };
 | |
|   A a(1, 2, 3);
 | |
| 
 | |
|   template<typename T> struct B {
 | |
|     template<int ...N> B(T, int (&...r)[N]);
 | |
|   };
 | |
|   B b(1, arr3, arr4);
 | |
| 
 | |
|   template<typename T> struct C {
 | |
|     template<template<typename> typename ...U> C(T, U<int>...);
 | |
|   };
 | |
|   C c(1, a, b);
 | |
| 
 | |
|   template<typename ...U> struct X {
 | |
|     template<typename T> X(T, U...);
 | |
|   };
 | |
|   X x(1, 2, 3);
 | |
| 
 | |
|   template<int ...N> struct Y {
 | |
|     template<typename T> Y(T, int (&...r)[N]);
 | |
|   };
 | |
|   Y y(1, arr3, arr4);
 | |
| 
 | |
|   template<template<typename> typename ...U> struct Z {
 | |
|     template<typename T> Z(T, U<int>...);
 | |
|   };
 | |
|   Z z(1, a, b);
 | |
| }
 | |
| 
 | |
| namespace tuple_tests {
 | |
|   // The converting n-ary constructor appears viable, deducing T as an empty
 | |
|   // pack (until we check its SFINAE constraints).
 | |
|   namespace libcxx_1 {
 | |
|     template<class ...T> struct tuple {
 | |
|       template<class ...Args> struct X { static const bool value = false; };
 | |
|       template<class ...U, bool Y = X<U...>::value> tuple(U &&...u);
 | |
|     };
 | |
|     tuple a = {1, 2, 3};
 | |
|   }
 | |
| 
 | |
|   // Don't get caught by surprise when X<...> doesn't even exist in the
 | |
|   // selected specialization!
 | |
|   namespace libcxx_2 {
 | |
|     template<class ...T> struct tuple { // expected-note {{candidate}}
 | |
|       template<class ...Args> struct X { static const bool value = false; };
 | |
|       template<class ...U, bool Y = X<U...>::value> tuple(U &&...u);
 | |
|       // expected-note@-1 {{substitution failure [with T = <>, U = <int, int, int>]: cannot reference member of primary template because deduced class template specialization 'tuple<>' is an explicit specialization}}
 | |
|     };
 | |
|     template <> class tuple<> {};
 | |
|     tuple a = {1, 2, 3}; // expected-error {{no viable constructor or deduction guide}}
 | |
|   }
 | |
| 
 | |
|   namespace libcxx_3 {
 | |
|     template<typename ...T> struct scoped_lock {
 | |
|       scoped_lock(T...);
 | |
|     };
 | |
|     template<> struct scoped_lock<> {};
 | |
|     scoped_lock l = {};
 | |
|   }
 | |
| }
 |