4

我正在为 x86 使用 DMD 2.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

然后抛出访问冲突错误。我是否错误地使用了笛卡尔产品,或者这是函数中的错误?

4

1 回答 1

6

Tiny bit of both, probably. The issue here is that ct is attempted to be evaluated at compile-time and produces result range that is used in run-time. I guess either CTFE or cartesianProduct does not expect such scenario and something bad happens that involves using invalid memory. I think it should have either work, or be a compile-time error, but that won't help you and belongs to bug tracker.

What does matter here, though is that everything will work if you move ct initialization to unit-test body or static this() module constructor. What you seem to miss is that D does not support initialization of global variables at program start-up. Value assigned to global is always evaluated at compile-time, which often "just works", often results in compile-time error (if initialization is not CTFE-able) and in this case results in weird behavior :)

What you may want is this code:

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

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

In general, interconnection between compile-time data and run-time data for complex types as arrays or associative arrays is very tricky with current D front-end implementation and requires lot of attention.

于 2013-03-27T09:40:13.603 回答