Изменилось ли требование о том, как переопределить виртуальную функцию?

Пожалуйста, посмотрите этот пример

      #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 baseв то время как Clang предлагает диагностику ошибки. В текущем черновике соответствующее правило определено следующим образом:
[class.virtual#2]

Если виртуальная функция-член F объявлена ​​в классе B, а в классе D, производном (прямо или косвенно) от B, объявление функции-члена G соответствует ([basic.scope.scope]) объявлению F , игнорируя завершающую требует-положений, то О переопределяет F .

Одновременно правило определения двух соответствующих объявлений определяется следующим образом:
[basic.scope#scope-3]

Два объявления соответствуют, если они (повторно) вводят одно и то же имя, оба объявляют конструкторы или оба объявляют деструкторы, если только

  • [...]
  • каждый объявляет функцию или шаблон функции, кроме случаев, когда
  • обе объявляют функции с одним и тем же списком-тип-параметра, эквивалентными ([temp.over.link]) завершающими предложениями-требованием (если есть, кроме указанных в [temp.friend]), и, если оба являются нестатическими членами , одинаковые cv-квалификаторы (если есть) и ref-qualifier ( если они есть у обоих ), или

В этом примере и имеют один и тот же список-типов-параметров, имеется один квалификатор ref, а его нет, поэтому последнее ограничение можно игнорировать, следовательно, для этих двух объявлений мы могли бы сказать, что они соответствуют. Следовательно, #2 отменяет #1который объявлен как виртуальная функция. Следовательно, мы можем сказать, что и GCC, и Clang имеют неправильный результат, если мы подчиняемся текущему проекту.

Однако в стандарте C ++ 20 ограничение на определение объявления, объявленного в производном классе, переопределяет виртуальную функцию, объявленную в базовом классе:
[class.virtual#2]

Если виртуальная функция-член vf объявлена ​​в классе Base и в классе Derived, производном прямо или косвенно от Base, функция-член vf с тем же именем, список-типов-параметров ([dcl.fct]), cv-qualification , и квалификатор ref (или его отсутствие) объявлен как Base :: vf, тогда Derived :: vf переопределяет Base :: vf.

Очевидно, что действующее правило изменило свой первоначальный смысл. Это недоработка в новом правиле? Или это просто искусственный замысел, заставляющий изменить требование?

0 ответов

Другие вопросы по тегам