Does the requirement for how to override a virtual function have changed?

Viewed 143

Please see this example

#include <iostream>
class B{
public:
    virtual void fun() &{  //#1
        std::cout<<"base\n";
    }
};
class A:public B{
public:
  void fun(){  //#2
      std::cout<<"override\n";
  }
};
int main(){
   A  a;
   B* ptr = &a;
   ptr->fun();
}

GCC prints base while Clang prompts an error diagnosis. In the current draft, the relevant rule is defined like that:
[class.virtual#2]

If a virtual member function F is declared in a class B, and, in a class D derived (directly or indirectly) from B, a declaration of a member function G corresponds ([basic.scope.scope]) to a declaration of F, ignoring trailing requires-clauses, then G overrides F.

Simultaneously, the rule for defining two declarations who correspond is defined like that:
[basic.scope#scope-3]

Two declarations correspond if they (re)introduce the same name, both declare constructors, or both declare destructors, unless

  • [...]
  • each declares a function or function template, except when
  • both declare functions with the same parameter-type-list, equivalent ([temp.over.link]) trailing requires-clauses (if any, except as specified in [temp.friend]), and, if both are non-static members, the same cv-qualifiers (if any) and ref-qualifier (if both have one), or

In this example, #1 and #2 have the same parameter-type-list, #1 has one ref-qualifier while #2 does not have, hence the latter restriction could be ignored, hence, for these two declarations, we could say they correspond. Hence, #2 overrides #1 that is declared as a virtual function. Hence, we could say both GCC and Clang have the wrong result if we obey the current draft.

However, in the c++20 standard, the restriction for how to determine a declaration declared in the derived class overrides the virtual function declared in the base class is:
[class.virtual#2]

If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or indirectly from Base, a member function vf with the same name, parameter-type-list ([dcl.fct]), cv-qualification, and ref-qualifier (or absence of same) as Base​::​vf is declared, then Derived​::​vf overrides Base​::​vf.

It's obvious that the current rule has changed its original meaning. Is it a defect in the new rule? Or, it's just the artificial design to make the requirement be changed?

0 Answers
Related