c++: robustify testcase [PR109752]
[official-gcc.git] / gcc / testsuite / g++.dg / template / conv17.C
blobf0f10f2ef4f1a8831ff2c211613e4d1db41620c8
1 // PR c++/101904
2 // Verify we stop at the first bad argument conversion when considering a
3 // candidate during overload resolution.
5 template<class T>
6 struct A { typedef typename T::type type; };
8 struct B {
9   // A conversion function that always induces a hard error when instantiated.
10   template<class T> B(T, typename A<T>::type = 0);
13 struct C {
14   template<class T> void f(T, typename A<T>::type); // #1
15   template<class T> void f(T, T) const;             // #2
17   static void g(int*, B);                           // #3
18   static void g(int, int);                          // #4
20 #if __cpp_ref_qualifiers
21   void h(B) &;                                      // #5
22   void h(int) &&;                                   // #6
23 #endif
26 int main() {
27   const C c;
29   // The bad conversion for the 'this' argument should preclude us from further
30   // considering the non-const #1 (which would have caused a hard error during
31   // instantiation).  This behavior is essentially DR 1391 extended to the
32   // 'this' argument.
33   c.f(0, 0); // resolves to #2
34   c.f<int>(0, 0);
36   // Likewise for the bad conversion for the 1st argument in #3.
37   C::g(42, 42); // resolves to #4
39 #if __cpp_ref_qualifiers
40   // Likewise for the bad 'this' conversion in #5.
41   C().h(0); // resolves to #6
42 #endif
45 #if __cpp_concepts
46 // Test the same calls in a SFINAE context.
47 template<class T>
48 concept D = requires (const T t) {
49   t.f(0, 0);
50   t.template f<int>(0, 0);
51   T::g(42, 42);
52   T().h(0);
55 static_assert(D<C>);
57 // Test that when there's no strictly viable candidate and we're in a
58 // SFINAE context, we still stop at the first bad argument conversion.
59 template<class T>
60 concept E = requires { T().h(nullptr); };
62 static_assert(!E<C>);
63 #endif