I'm using DMD 2.062 for x86.
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);
}
}
This program prints out:
one one
two one
three one
Then an access violation error is thrown. Am I using cartesianProduct incorrectly, or is this a bug in the function?
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.