Consider the following simple concept
:
template <typename T>
concept C = requires(T a) { a.f(); };
What should happens if we take an abstract class type as the requires expressions's argument?
struct B { virtual void f() = 0; };
static_assert(C<B>);
gcc-trunk and msvc-trunk pass the assertion, however, clang-trunk, gcc-10.2, and msvc v19.24 reject the assertion.
What does the standard say?
GCC-trunk and MSVC-trunk are correct. The restrictions on the use of abstract types have changed between C++17 and C++20 thanks to P0929. Consequently, even ordinary function declarations with abstract parameter types are now allowed:
void foo(B b); // ill-formed in C++17, well-formed in C++20
void foo(B b) { /* ... */ } // still ill-formed in C++20
The wording "An abstract class shall not be used as a parameter type..." (C++17 [class.abstract]/3) was removed. In C++20, it is ill-formed for a function to have an abstract parameter type only if the function is being called ([expr.call]/7) or defined ([dcl.fct.def.general]/2). Furthermore, a parameter-declaration found in a requires-parameter-list is not a definition, just like how a parameter-declaration found in a non-defining declaration of a function is not a definition ([basic.def]/2.8).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With