xref: /llvm-project/clang/test/CXX/temp/temp.deduct.guide/p3.cpp (revision 4ad4d34a226043a5d594b261a9c2a50efd292a76)
1 // RUN: %clang_cc1 -std=c++1z %s -verify
2 
3 // The same restrictions apply to the parameter-declaration-clause of a
4 // deduction guide as in a function declaration.
5 template<typename T> struct A {};
6 A(void) -> A<int>; // expected-note {{previous}}
7 A(void, int) -> A<int>; // expected-error {{'void' must be the first and only parameter if specified}}
8 
9 A() -> A<int>; // expected-error {{redeclaration of deduction guide}}
10 // expected-note@-1 {{previous}}
11 
12 A() -> A<int>; // expected-note {{previous}}
13 // expected-error@-1 {{redeclaration of deduction guide}}
14 A() -> A<float>; // FIXME: "functions" is a poor term. expected-error {{functions that differ only in their return type cannot be overloaded}}
15 
16 template<typename T> A(T) -> A<typename T::foo>;
17 template<typename T> A(T) -> A<typename T::bar>; // ok, can overload on return type (SFINAE applies)
18 
19 A(long) -> A<int>;
20 template<typename T = int> A(long) -> A<char>; // ok, non-template beats template as usual
21 
22 // (Pending DR) The template-name shall name a class template.
23 template<typename T> using B = A<T>; // expected-note {{template}}
24 B() -> B<int>; // expected-error {{cannot specify deduction guide for alias template 'B'}}
25 // FIXME: expected-error@-1 {{declarator requires an identifier}}
26 template<typename T> int C;
27 C() -> int; // expected-error {{a type specifier is required}}
28 template<typename T> void D();
29 D() -> int; // expected-error {{a type specifier is required}}
30 template<template<typename> typename TT> struct E { // expected-note 2{{template}}
31   // FIXME: Should only diagnose this once!
32   TT(int) -> TT<int>; // expected-error 2{{cannot specify deduction guide for template template parameter 'TT'}} expected-error {{requires an identifier}}
33 };
34 
35 A(int) -> int; // expected-error {{deduced type 'int' of deduction guide is not a specialization of template 'A'}}
36 template <typename T> A(T)->B<T>;         // expected-error {{deduced type 'B<T>' (aka 'A<T>') of deduction guide is not written as a specialization of template 'A'}}
37 template<typename T> A(T*) -> const A<T>; // expected-error {{deduced type 'const A<T>' of deduction guide is not a specialization of template 'A'}}
38 
39 // A deduction-guide shall be declared in the same scope as the corresponding
40 // class template.
41 namespace WrongScope {
42   namespace {
43     template<typename T> struct AnonNS1 {}; // expected-note {{here}}
44     AnonNS1(float) -> AnonNS1<float>; // ok
45   }
46   AnonNS1(int) -> AnonNS1<int>; // expected-error {{deduction guide must be declared in the same scope as template 'WrongScope::}}
47   template<typename T> struct AnonNS2 {}; // expected-note {{here}}
48   namespace {
49     AnonNS1(char) -> AnonNS1<char>; // ok
50     AnonNS2(int) -> AnonNS2<int>; // expected-error {{deduction guide must be declared in the same scope as template 'WrongScope::AnonNS2'}}
51   }
52   namespace N {
53     template<typename T> struct NamedNS1 {}; // expected-note {{here}}
54     template<typename T> struct NamedNS2 {}; // expected-note {{here}}
55   }
56   using N::NamedNS1;
57   NamedNS1(int) -> NamedNS1<int>; // expected-error {{deduction guide must be declared in the same scope as template}}
58 
59   using namespace N;
60   NamedNS2(int) -> NamedNS2<int>; // expected-error {{deduction guide must be declared in the same scope as template}}
61   struct ClassMemberA {
62     template<typename T> struct X {}; // expected-note {{here}}
63   };
64   struct ClassMemberB : ClassMemberA {
65     X(int) -> X<int>; // expected-error {{deduction guide must be declared in the same scope as template 'WrongScope::ClassMemberA::X'}}
66   };
67   template<typename T> struct Local {};
68   void f() {
69     Local(int) -> Local<int>; // expected-error {{expected}}
70     using WrongScope::Local;
71     Local(int) -> Local<int>; // expected-error {{expected}}
72   }
73 }
74