2011-10-06

非staticデータメンバーの初期化子

今月にビルドされたgcc4.7で対応していることを確認。

struct S
{
    int member = 123 ;
    S() = default ;
    S( int value ) : member(value) { }
} ;


int main()
{
    S s1 ; // s.member == 123
    S s2(456) ; // s.member == 456
}

なお、非staticデータメンバーの宣言にauto specifierを使うことはできない。これは、auto specifierが、ブロック、名前空間スコープ、for文の初期化句にしか使われてはならないとされているためである。

struct S
{
    auto member = 0 ; // error
} ;

ちなみに言っておくと、staticデータメンバーにはauto specifierを使うことができる。これは、staticデータメンバーが、実は名前空間スコープであるからだ。staticデータメンバーは、クラス定義の中に書かなければならないとか、クラス名による修飾をしなければならないなどの制約はあるが、名前空間スコープに属する名前である。

struct S
{
    static auto const member = 0 ; // OK, type is determined to be "const int"
} ;

もちろん、staticデータメンバーに初期化子が許されているのは、constなリテラル型だけであるので、autoがそれ以外の型に推定された場合は、エラーとなる。

struct S
{
    static auto member = 0 ; // Error, the type of static member is not const literal type.
} ;

ちなみに、gccには七ヶ月前、上記のコードを通してしまうバグがあったが、バグレポートを送ったところ、現在では修正されている。

1 comment:

Anonymous said...

> auto specifierが、ブロック、名前空間スコープ、for文の初期化句にしか使われてはならないとされている
...
> これは、staticデータメンバーが、実は名前空間スコープであるからだ。

7.1.6.4 p4 の "The auto type-specifier can also be used in declaring a variable in ..." を見落とされているようです。同 7.1.6.4 の p3 に挙げられている上記3つ以外に、初期化子付き static データメンバの宣言を含めていろいろと auto が使える場所が挙げられています。それでもやっぱり non-static データメンバは含まれませんが。