10

C++11 では、型指定子にはクラス指定子列挙指定子が含まれます。(別名クラス定義と列挙定義)

文法/構文によると、型指定子は言語のいくつかの場所に現れる可能性がありますが、それらすべての場所でクラス指定子と列挙指定子が許可されているわけではありません。

例えば:

struct C{} c;
// ok: types may be defined in the specifiers of a simple declaration

void f(struct S{});
// error: types may not be defined in parameter types

constexpr auto i = sizeof(enum E{});
// error: types may not be defined in ‘sizeof’ expressions

標準のどこで、これらの型指定子の使用を、型が定義されている場合と定義されていない場合に分けていますか? たとえば、sizeof 式で型を定義してはならないというルールはどこにありますか?

4

2 に答える 2

8

C++ 標準で見つからない理由は、C 標準からのデルタで実際に禁止されているためです。

C.1.4 には、次のようなものがあります。Change: Types must be declared in declarations, not in expressions In C, a sizeof expression or cast expression may create a new type.これは、問題の禁止を示しています。

これは 7.1.6/3 で明示的に呼び出されます。

コンストラクタ、デストラクタ、または変換関数を宣言する場合を除き、cv-qualifier ではない少なくとも 1 つの型指定子が宣言に必要です。テンプレート宣言の宣言ではない別名宣言 (7.1.3) の ID。

特に関心のある部分はA type-specifier-seq shall not define a class or enumeration unless...

于 2014-01-07T20:38:48.997 に答える
3

N3797 から:

8.3.5/9 戻り値またはパラメータの型で型を定義してはならない。関数定義のパラメーターの型または戻り値の型は、関数が削除されるか ( 8.4.3 )、定義がそのクラスのメンバー仕様内にネストされない限り (おそらく cv 修飾された) 不完全なクラス型であってはなりません (クラス内で定義されたネストされたクラスの定義を含む)。

これは、関数宣言で新しい型を定義することをブロックします。

次の 2 つは、OP で言及されていない他のコーナー ケースです。

11.3/2 フレンド宣言でクラスを定義してはならない。

14.1/2 型は、テンプレート パラメータ宣言で定義してはなりません。

最後に、この句はそれsizeofを他の場所でブロックします。

7.1.6/3 type-specifier-seq は、テンプレート宣言の宣言ではないエイリアス宣言 (7.1.3) の type-id に現れない限り、クラスまたは列挙を定義してはならない

Cにはその制限がないことに注意してください(C.1.4)

さらに、以前のバージョンの C++ 標準には、次のものがありました。

5.3.3p5 型は sizeof 式で定義してはならない

これは、最新バージョンの標準提案では見つけることができず、N3797 の下では冗長ですsizeof。文法で型を定義する s ルートは viatype-specifier-seqであり、7.1.6/3 によってブロックされているためです。

sizeof(type-id)-> type-id-> type-specifer-seq-> type-specifier->class-specifier

于 2014-01-07T20:39:09.240 に答える