Skip to content

[class.virtual] Corresponding declaration vs. overriding a virtual function CWG2496 #4699

@xmh0511

Description

@xmh0511

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:

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:

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.

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:

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?

Metadata

Metadata

Assignees

No one assigned

    Labels

    cwgIssue must be reviewed by CWG.not-editorialIssue is not deemed editorial; the editorial issue is kept open for tracking.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions