こう書いてある。
12.1 Constructors [class.ctor] paragraph 5
A defaulted default constructor for class X is defined as deleted if:
(省略)
any *non-variant* non-static data member of const-qualified type (or array thereof) with no brace-or- equal-initializer does not have a user-provided default constructor,
X is a union and *all* of its variant members are of const-qualified type (or array thereof),
non-variantという条件があるから、一つ目の条件は、variant memberには当てはまらない。つまり、unionには当てはまらない条件である。(おそらく規格外ではあまり使われていないだろうが、unionの共用されるデータメンバーには、規格ではvariant memberという名称がある。)
二つ目の条件には、all of its variant membersとある。とすれば、const-qualified typeとconst-unqualified typeの両方をvariant memberに持つunionのデフォルトコンストラクターは暗黙にdeletedされないはずである。ということは、以下のコードはwell-formedということになる。
union X { int a ; int const b ; } ; int main () { X x ; // well-formed }
しかし、MSVC、GCC、Comeauは、すべて、エラーとする。
もちろん、これらのコンパイラーは、まだC++0xを完全に実装していない。しかし、このような根本的な言語仕様は、C++03から変わっていないのではないだろうか。C++03の規格の定義では、「もし、ユーザーによって書かれた、暗黙のデフォルトコンストラクターと同等のコードがill-formedになる場合は、ill-formedである」などと定義されている。C++0xでは、explicitly-defaulted functionや、deleted definitionがあるので、いつdeleted定義されるのかというルールを詳細に記述している。そのルールは、C++03を受け継いでいるはずだ。このような根本的な仕様がC++0xで変更されたのだろうか。
不思議に思って質問してみると、だいぶ最近の、Core issue 922による変更らしい。2009年の11月だ。
結論として、unionのvariate memberは、constと非constな型を混ぜて使える。その際、ひとつでも非constな型があれば、暗黙のデフォルトコンストラクターが使える。
ところで、C++0xのunionは、コンストラクターやデストラクターも含むメンバー関数を持てるので、だいぶ様変わりしている。C++0xでは、unionはかなり使いやすくなったはずだ。
No comments:
Post a Comment