2016-11-15 17 views
2

なぜ、この有効なC++ではありません?:別の列挙型の基になる型として列挙型を使用できないのはなぜですか?

enum foo : unsigned { first_foo, second_foo }; 
enum bar : foo { best_foo = first_foo }; 

GCC 5.4.0は言う:

/tmp/a.cpp:3:16: error: underlying type ‘foo’ of ‘bar’ must be an integral type 
    enum bar : foo { best_foo = first_foo }; 

foofloat、またはいくつかの構造体であれば、私はこのエラーを取得する理由私は理解することができ、または何もない。しかし、これはセマンティクス、型の安全性などの点で私には完全に正当だと思われます。何が欠けていますか?

+2

なぜですか?スタンダードはそうそうだ。 :) – Zereges

+0

@Zereges:[しかし...なぜ?](https://cdn.meme.am/cache/instances/folder489/500x/59809489.jpg) – einpoklum

+1

通常の理由は、[一部の人が提案を書いた] (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2347.pdf)、提案された内容が受け入れられました。 –

答えて

2

C++に追加すると、問題を解決する最小限の量を追加する傾向があります。

enum A:int構文では、enum Aが整数として格納される方法を正確に指定できます。それがすべてであり、問​​題を解決します。

enum A:BBは、多くの意味を持つことができます。 ABを拡張できます。Aは、異なる名前を持つB基本タイプのサブセットです。Aは、厳密には、Bに格納できる値のサブセットを持つことができます。Aは、 「船体」はBの値に制限されています。

これらのうち、同じ基本型ソリューション(:int構文)はenum A:std::underlying_type_t<B>と並んでいます。だからすでにそれを行う方法があり、それは特に厄介ではない。

誰かがenum A:Bが意味するべきことを示唆し、委員会を十分に説得するまでは、許可される可能性は低いです。そして、複数の異なる妥当な意味がある場合、これは、いずれかの意味が選択されることをより困難にする。 1つの特定の意味が最も優れている理由と、それを標準にする努力をする価値がある理由についての強いユースケースが必要です。

+0

さて、あなたが好きなら、あなたは私の[ユースケース](http://stackoverflow.com/q/40607928/1593077)を見て、それがどれほど魅力的かどうかを突き止めることができます。 – einpoklum

3

まあ、まったく同じではないが、私はあなたがstd::underlying_typeを使用できると思う:

enum foo : unsigned { first_foo, second_foo }; 
enum bar : std::underlying_type_t<foo> { best_foo = first_foo }; 
+0

それは私が使用している回避策ですが、それは私の質問ではありません... – einpoklum

+2

@einpoklumまあ、あなたはあなたの質問に言及しなかったので、どうすればわかるでしょうか?なぜあなたのニーズを満たしていないのか分かりません。とにかく基本的な型変換になると、通常の 'enum'はかなり弱いです。 –

+1

私の質問は「なぜ」なのですか?それは2回、非常に明示的に書いています... – einpoklum

7

C++ 11 [dcl.enum]/2:

型specifier- seqenum-baseは、整数型の名前を付けます。 cv-qualificationは無視されます。

タイプboolcharchar16_tchar32_twchar_t、および符号付きおよび符号なし整数型をまとめて積分と呼ばれている。

列挙自体が– [basic.fundamental]/7が整数型ではありませんタイプ。

これは、非規範的な脚注を伴う:

したがって、列挙型は整数ではありません。ただし、[conv.prom]で指定されているように、列挙型を整数型に昇格できます。私はあなたが探していると思うの効果を達成するために

は、しかし、まだ簡単です:私にとって

enum bar : std::underlying_type<foo>::type { best_foo = first_foo }; 
+0

それは直ちに正式な理由ですが、型指定子seq名は整数型または列挙型ではなく整数型でなければならないのはなぜですか? – einpoklum

+0

@einpoklum:これは、この種のサイトにとっては遠い問題です。私はC++委員会にいないので、私はどのように知ることができるのか分かりません。 ; - ] – ildjarn

+0

委員会にいるか、仕事に従事している人が頻繁にこのサイトを訪ねて質問に答えます。 Bjarneは一度私に答えました。 – einpoklum

3

列挙型が別の列挙型に基づくことができると言って論理的なエラーです。列挙型で定義されている値が格納されている記憶域の型であると思うなら、記憶域の種類が列挙型であると言う論理式として取得できません。列挙型は記憶域タイプだけでなく、有効な値のセットも含んでいます。

我々のような何かを書くことができた場合:

enum A: int { ONE, TWO }; 

意味すべきか:

enum B: A{}; 

をAは下層のタイプ(私は、このストレージタイプ呼び出す)だけでなく、一連のではないだけを定義しているので有効な値は、列挙型Aのサブセットのみである必要があります。つまり、すでにAで定義されている値のみを定義できますか?

Bですでに定義されている値のうち1つ、2つを習得することは有効ですか? そして、次のように複数の値を追加できるようになりました:

enum B: A{THREE}; 

と、すべての有効な値は、今ONE、TWO、THREEですか?

または私たちはサブセットのみを取得意味です:

enum B: A{ONE}; 

Bは、すでにAで定義された値を使用することができるだけでそれが列挙型に別の列挙型のベースを作るために私にはそれが困難になることを意味します。

このドアを開くと、下敷きのストレージタイプをビットフィールドのような他の種類のものから使いたいという考えも出てくるでしょう。

struct A { unsigned int a : 3; unsigned int B: 2; }; 

はその後

enum B: A { ONE, TWO }; 

も有効でなければなりませんか?私は信じていない! ;)

論理ポイント(私の見解)から、列挙型の下位タイプはその記憶タイプです。また、列挙型を別の列挙型の下位記憶型として作成することは意味がありません。

+1

"enum Aのサブセットであるべきですか?"はい、私はそう実際には思うでしょう。 – einpoklum

+0

@einpoklumサブセットのみにすることができれば、それは構造体/クラスから派生するのと反対です。派生クラスでのみ基本クラスを拡張することができるためです。それで、列挙型の論理を逆転させるのは論理的に大丈夫ですか? ;) – Klaus

+0

クラウス:そうではありません。継承は、基本クラスを拡張するのではなく、基本クラスを収縮させるためによく使用されます。継承されたクラスの間には、「どちらかといえば、どちらかといえば」と「どちらかといえば、ただの」関係があります。 – einpoklum

関連する問題