xref: /llvm-project/clang/test/CXX/temp/temp.fct.spec/temp.deduct/p7.cpp (revision 974c8b7e2fde550fd87850d50695341101c38c2d)
1 // RUN: %clang_cc1 -std=c++11 -verify %s
2 // RUN: %clang_cc1 -std=c++2a -verify %s
3 
4 struct Q { typedef int type; };
5 
6 // "The substitution occurs in all types and expressions that are used in [...]
7 // template parameter declarations." In particular, we must substitute into the
8 // type of a parameter pack that is not a pack expansion, even if we know the
9 // corresponding argument pack is empty.
10 template<typename T, typename T::type...> void a(T);
11 int &a(...);
12 int &a_disabled = a(0);
13 int &a_enabled = a(Q()); // expected-error {{cannot bind to a temporary of type 'void'}}
14 
15 template<typename T, template<typename T::type> class ...X> void b(T);
16 int &b(...);
17 int &b_disabled = b(0);
18 int &b_enabled = b(Q()); // expected-error {{cannot bind to a temporary of type 'void'}}
19 
20 template<typename T, template<typename T::type...> class ...X> void c(T);
21 int &c(...);
22 int &c_disabled = c(0);
23 int &c_enabled = c(Q()); // expected-error {{cannot bind to a temporary of type 'void'}}
24 
25 // The substitution proceeds in lexical order and stops when a condition that
26 // causes deduction to fail is encountered.
27 #if __cplusplus > 201702L
28 namespace reversed_operator_substitution_order {
29   struct X { X(int); };
30   struct Y { Y(int); };
31   struct Cat {};
32   namespace no_adl {
33     Cat operator<=>(Y, X);
34     bool operator<(int, Cat);
35 
36     template<typename T> struct indirect_sizeof {
37       static_assert(sizeof(T) != 0);
38       static const auto value = sizeof(T);
39     };
40 
41     // We should substitute into the construction of the X object before the
42     // construction of the Y object, so this is a SFINAE case rather than a
43     // hard error. This requires substitution to proceed in lexical order
44     // despite the prior rewrite to
45     //    0 < (Y(...) <=> X(...))
46     template<typename T> float &f(
47         decltype(
48           X(sizeof(T)) < Y(indirect_sizeof<T>::value)
49         )
50     );
51     template<typename T> int &f(...);
52   }
53   int &r = no_adl::f<void>(true);
54   float &s = no_adl::f<int>(true);
55 }
56 #endif
57