A virtual function cannot have a trailing requires-clause. However, while a virtual function is present in a class or class template, currently there is nothing prohibiting a non-virtual
non-member function with the same parameter-type-list, the same cv-qualifiers (if any) and ref-qualifier (if any), and a trialing requires-clause to be declared in the same class or class template, because the two declarations do not correspond ([basic.scope.scope]/(3.3.1)).
So following code is currently well-formed, where both the virtual and the non-virtual overloads are odr-used:
template<int N>
struct Foo {
virtual int bar() const { return N; }
int bar() const requires (N > 0) { return 0; }
};
int main()
{
Foo<42>{}.bar();
}
But such overloading cannot be properly supported on Itanium C++ ABI, where two Foo<42>::bar overloads share the same mangled name "_ZNK3FooILi42EE3barEv”.
Clang 11 accepts it with option “-std=c++2a -O2” (https://gcc.godbolt.org/z/fP4YTf)
but rejects it with option “-std=c++2a” (https://gcc.godbolt.org/z/rE8sjP).
On the other hand, such overloading can be supported by MSVC, because mangled names of virtual and non-virtual functions are always different on MS ABI.
I think this kind of overloading should be conditionally supported, and diagnostic should be required on platforms that cannot support it properly.
(I have mailed to
wmm@edg.com twice for this issue but have not been replied yet.)
Jiang An