4

x86用にDMD2.062を使用しています。

module test;    

private enum test1
{
    one,
    two,
    three,
}

private enum test2
{
    one,
    two,
    three,
}

auto ct = cartesianProduct([EnumMembers!test1], [EnumMembers!test2]);

unittest
{
    import std.stdio;
    foreach (n, m; ct)
    {
        writeln(n, " ", m);
    }
}

このプログラムは次のように出力します。

one one
two one
three one

次に、アクセス違反エラーがスローされます。CartesianProductを誤って使用していますか、それとも関数のバグですか?

4

1 に答える 1

6

おそらく、両方のほんの少し。ここでの問題はct、コンパイル時に評価され、実行時に使用される結果範囲を生成しようとすることです。CTFEまたはcartesianProductのどちらもそのようなシナリオを予期しておらず、無効なメモリの使用を伴う何か悪いことが起こっていると思います。動作するか、コンパイル時のエラーになるはずですが、それは役に立たず、バグトラッカーに属します。

ctただし、ここで重要なのは、初期化を単体テスト本体またはstatic this()モジュールコンストラクターに移動するとすべてが機能することです。あなたが見逃しているように見えるのは、Dがプログラムの起動時にグローバル変数の初期化をサポートしていないことです。グローバルに割り当てられた値は常にコンパイル時に評価されます。これは多くの場合「正常に機能」し、コンパイル時エラーが発生することが多く(初期化がCTFEに対応していない場合)、この場合は奇妙な動作になります:)

あなたが望むかもしれないのはこのコードです:

auto Test1Members = [ EnumMembers!test1 ];
auto Test2Members = [ EnumMembers!test2 ];
alias CT = typeof(cartesianProduct(Test1Members, Test2Members));
CT ct;

static this()
{
    ct = cartesianProduct(Test1Members, Test2Members);
}

一般に、配列または連想配列などの複雑な型のコンパイル時データと実行時データ間の相互接続は、現在のDフロントエンドの実装では非常に注意が必要であり、多くの注意が必要です。

于 2013-03-27T09:40:13.603 に答える