CV-квалифицированные базовые классы в С++
Во время рефакторинга кода С++ 11 я наткнулся на странную вещь. А именно, представляется невозможным определить базовый класс с квалификацией CV (const
, volatile
или const volatile
), например:
struct A { int a = 0; };
struct B: A const {}; // Error here with Clang and GCC!
Однако следующие компиляции без ошибок:
struct A { int a = 0; };
using AC = A const;
struct B: AC {}; // NO ERROR HERE!? Qualifiers are ignored.
int main() {
B b;
b.a = 42; // NO ERROR modifying a field of const base.
return b.a;
}
У меня есть два вопроса:
- Что в стандартах С++ запрещает определять базовый класс с квалификацией CV, если вообще?
- Почему второй пример компилируется?
PS: Поскольку это вопрос language-lawyer, просьба указать ссылки на стандарт С++.
Ответы
Ответ 1
-
Грамматика запрещает это. Базовые классы задаются производством базового предложения, указанным в начале раздела 10 стандарта. В конечном итоге он решает спецификатор базового типа, который является классом-или-decltype, который является либо конструкцией decltype
, либо именем класса-в-вложенном-name-specifier [opt]. Обратите внимание, что это не оставляет места для cv-спецификатора.
-
Имя typedef соответствует грамматике. 9.1/5 говорит: "Имя типа typedef, которое называет тип класса, или его версию с квалификацией cv, также является именем класса". Константа просто игнорируется.
-
Константа просто игнорируется. Субобъекты базового класса не могут быть константными сами по себе. 9.1/5 говорит: "Если имя typedef, которое называет класс класса с квалификацией, используется там, где требуется имя класса, cv-квалификаторы игнорируются".
Ответ 2
На самом деле это полный объект, который вы создаете, который является константой или не const, классы не имеют квалификации.
В using AC = A const;
const просто игнорируется при использовании для наследования.