2016-03-11 9 views
20

一部のC++ 11コードをリファクタリングしているうちに、私は奇妙なことに遭遇しました。すなわち、CV-資格(constvolatileまたはconst volatile)基底クラス、例えばを定義することは不可能であるように思わ:C++のCV修飾ベースクラス

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; 
} 

私は2つを持っています質問:

  1. C++標準ではCV認定ベースクラスの定義は禁止されていますか?
  2. 2番目の例はなぜコンパイルされますか?

PS:これは言語弁護士質問ですので、C++標準への参照を提供してください。

+4

あなたはまだconstの組成物を用いることがあります... – Jarod42

+0

jarrod42が言ったことに加えて、「'Bをconst'される」何を意味するのでしょうか? Bも 'const'ではないですか? – rubenvb

答えて

21
  1. 文法はそれを禁止します。基本クラスは、標準の第10章の始めに指定されたベース節プロダクションで指定されます。これは、最終的decltype構築物またはネスト名指定子[OPT]クラス名のいずれかであるクラスまたは-decltype、ある塩基型指定子に解決します。これはcv指定子のための場所を残さないことに注意してください。

  2. typedef名は文法に適合します。 9.1/5は、 "クラス型またはそのクラスの名前を付けるtypedef-nameもクラス名である"と述べています。 constは単に無視されます。

  3. constは単に無視されます。基本クラスのサブオブジェクトは、単独ではconstにすることはできません。 9.1/5は、 "class-nameが必要な場合にcv修飾されたクラス型を指定するtypedef-nameが使用されている場合、cv-qualifierは無視されます。"

+0

また、9.1/5にも "A *クラス型またはそのcv修飾バージョンの名前を指定するtypedef-name *(7.1.3)も*クラス名*です。標準の文法規則には* class-name *の* typedef-name *は明示的に含まれていません。なんらかの理由で、これは付録の注記のみが与えられています。 – jotik

7

実際に作成するオブジェクトは、constまたはconstではないクラスであり、クラスはcv修飾されていません。

using AC = A const;では、継承に使用するとconstは単に無視されます。

+0

はい、私は考えましたが、なぜですか? – jotik

+0

'AC'は本当に' A'だけではなく 'A'です。[デモ](http://coliru.stacked-crooked.com/a/6cf24bd593d2f895)です。 – Jarod42

+0

@jotik定義された父親はcvパーティション化されたオブジェクトの使用を見ていませんでしたが、私はそれがこの決定の背後にあるとは思わない – Jojje