プログラム系統備忘録ブログ

記事中のコードは自己責任の下でご自由にどうぞ。

C++/CLIにてコンパイルエラーC2360やC2361が配列の部分で起きる話

VisualStudio2012で確認。
switchとgcnew arrayを使った以下のC++/CLIのソースがコンパイルエラーになります。

int main(){
    array<int> ^a;
    switch(0){
    case 0:
        a = gcnew array<int>{};
        break;
    case 1:
        a = gcnew array<int>{1};
        break;
    default:
        a = gcnew array<int>{2,2};
        break;
    }
    System::Console::WriteLine(a->Length);
    return 0;
}
1>main.cpp(7): error C2360: '$S1' の初期化が 'case' ラベルによって行われませんでした。
1>          main.cpp(5) : '$S1' の宣言を確認してください。
1>main.cpp(10): error C2361: '$S2' の初期化が 'default' ラベルによって行われませんでした。
1>          main.cpp(8) : '$S2' の宣言を確認してください。
1>main.cpp(10): error C2361: '$S1' の初期化が 'default' ラベルによって行われませんでした。
1>          main.cpp(5) : '$S1' の宣言を確認してください。

コンパイルエラーを回避するには、switch文の中で配列を初期化子リストで作成している部分を以下のようにブロックで囲います。
もちろん、switch文の条件を変えると出力も変わります。

int main(){
    array<int> ^a;
    switch(0){
    case 0:
        {
            a = gcnew array<int>{};
        }
        break;
    case 1:
        {
            a = gcnew array<int>{1};
        }
        break;
    default:
        {
            a = gcnew array<int>{2,2};
        }
        break;
    }
    System::Console::WriteLine(a->Length);
    return 0;
}

"a = gcnew array(n);"の形式ではcase節直下にあってもコンパイルエラーは発生しません。また初期化子リストを使っていてもC#では問題は発生しません。ううむ、面倒くさいものです。