111
|
1 // { dg-do run }
|
|
2 // { dg-options "-std=c++17 -fconcepts" }
|
|
3
|
|
4 #include <cassert>
|
|
5 #include <type_traits>
|
|
6
|
|
7 template<typename T>
|
|
8 concept bool C() { return __is_class(T); }
|
|
9
|
|
10 template<typename T>
|
|
11 concept bool Type() { return true; }
|
|
12
|
|
13 struct S { };
|
|
14
|
|
15 int called;
|
|
16
|
|
17 // Basic terse notation
|
|
18 void f(auto x) { called = 1; }
|
|
19 void g(C x) { called = 2; }
|
|
20
|
|
21 // Overloading generic functions
|
|
22 void h(auto x) { called = 1; }
|
|
23 void h(C x) { called = 2; }
|
|
24
|
|
25 void p(auto x);
|
|
26 void p(C x);
|
|
27
|
|
28 struct S1 {
|
|
29 void f1(auto x) { called = 1; }
|
|
30 void f2(C x) { called = 2; }
|
|
31
|
|
32 void f3(auto x) { called = 1; }
|
|
33 void f3(C x) { called = 2; }
|
|
34 };
|
|
35
|
|
36 template<C T>
|
|
37 struct S2 {
|
|
38 void f1(auto x) { called = 1; }
|
|
39 void f2(C x) { called = 2; }
|
|
40
|
|
41 void f3(auto x) { called = 1; }
|
|
42 void f3(C x) { called = 2; }
|
|
43
|
|
44 void h1(auto x);
|
|
45 void h2(C x);
|
|
46
|
|
47 void h3(auto x);
|
|
48 void h3(C x);
|
|
49
|
|
50 template<C U>
|
|
51 void g1(T t, U u) { called = 1; }
|
|
52
|
|
53 template<C U>
|
|
54 void g2(T t, U u);
|
|
55 };
|
|
56
|
|
57
|
|
58 void ptr(C*) { called = 1; }
|
|
59 void ptr(const C*) { called = 2; }
|
|
60
|
|
61 void ref(C&) { called = 1; }
|
|
62 void ref(const C&) { called = 2; }
|
|
63
|
|
64 void
|
|
65 fwd_lvalue_ref(Type&& x) {
|
|
66 using T = decltype(x);
|
|
67 static_assert(std::is_lvalue_reference<T>::value, "not an lvlaue reference");
|
|
68 }
|
|
69
|
|
70 void
|
|
71 fwd_const_lvalue_ref(Type&& x) {
|
|
72 using T = decltype(x);
|
|
73 static_assert(std::is_lvalue_reference<T>::value, "not an lvalue reference");
|
|
74 using U = typename std::remove_reference<T>::type;
|
|
75 static_assert(std::is_const<U>::value, "not const-qualified");
|
|
76 }
|
|
77
|
|
78 void fwd_rvalue_ref(Type&& x) {
|
|
79 using T = decltype(x);
|
|
80 static_assert(std::is_rvalue_reference<T>::value, "not an rvalue reference");
|
|
81 }
|
|
82
|
|
83 // Make sure we can use nested names speicifers for concept names.
|
|
84 namespace N {
|
|
85 template<typename T>
|
|
86 concept bool C() { return true; }
|
|
87 } // namesspace N
|
|
88
|
|
89 void foo(N::C x) { }
|
|
90
|
|
91 int main() {
|
|
92 S s;
|
|
93 const S cs;
|
|
94
|
|
95 f(0); assert(called == 1);
|
|
96 g(s); assert(called == 2);
|
|
97
|
|
98 h(0); assert(called == 1);
|
|
99 h(s); assert(called == 2);
|
|
100
|
|
101 S1 s1;
|
|
102 s1.f1(0); assert(called == 1);
|
|
103 s1.f2(s); assert(called == 2);
|
|
104
|
|
105 s1.f3(0); assert(called == 1);
|
|
106 s1.f3(s); assert(called == 2);
|
|
107
|
|
108 S2<S> s2;
|
|
109 s2.f1(0); assert(called == 1);
|
|
110 s2.f2(s); assert(called == 2);
|
|
111
|
|
112 s2.f3(0); assert(called == 1);
|
|
113 s2.f3(s); assert(called == 2);
|
|
114
|
|
115 s2.h1(0); assert(called == 1);
|
|
116 s2.h2(s); assert(called == 2);
|
|
117
|
|
118 s2.h3(0); assert(called == 1);
|
|
119 s2.h3(s); assert(called == 2);
|
|
120
|
|
121 s2.g1(s, s); assert(called == 1);
|
|
122 s2.g2(s, s); assert(called == 2);
|
|
123
|
|
124 ptr(&s); assert(called == 1);
|
|
125 ptr(&cs); assert(called == 2);
|
|
126
|
|
127 ref(s); assert(called == 1);
|
|
128 ref(cs); assert(called == 2);
|
|
129
|
|
130 // Check forwarding problems
|
|
131 fwd_lvalue_ref(s);
|
|
132 fwd_const_lvalue_ref(cs);
|
|
133 fwd_rvalue_ref(S());
|
|
134
|
|
135 foo(0);
|
|
136 }
|
|
137
|
|
138 // Test that decl/def matching works.
|
|
139
|
|
140 void p(auto x) { called = 1; }
|
|
141 void p(C x) { called = 2; }
|
|
142
|
|
143 template<C T>
|
|
144 void S2<T>::h1(auto x) { called = 1; }
|
|
145
|
|
146 template<C T>
|
|
147 void S2<T>::h2(C x) { called = 2; }
|
|
148
|
|
149 template<C T>
|
|
150 void S2<T>::h3(auto x) { called = 1; }
|
|
151
|
|
152 template<C T>
|
|
153 void S2<T>::h3(C x) { called = 2; }
|
|
154
|
|
155 template<C T>
|
|
156 template<C U>
|
|
157 void S2<T>::g2(T t, U u) { called = 2; }
|