我试图学习D并遇到结构和初始化问题。当以下代码编译为rdmd -version=templat code.d
时,我收到一堆错误,例如:
> dmd -version=templat code.d
D:\D\dmd2\windows\bin\..\..\src\phobos\std\random.d(1610): Error: static variable initialized cannot be read at compile time
D:\D\dmd2\windows\bin\..\..\src\phobos\std\random.d(1653): called from here: rndGen()
D:\D\dmd2\windows\bin\..\..\src\phobos\std\random.d(1653): called from here: uniform(a, b, rndGen())
code.d(8): called from here: uniform(1u, 7u)
D:\D\dmd2\windows\bin\..\..\src\phobos\std\range\package.d(3470): called from here: (*function () => uniform(1u, 7u))()
D:\D\dmd2\windows\bin\..\..\src\phobos\std\range\package.d(3387): called from here: gen.popFront()
code.d(8): called from here: generate()
code.d(13): Error: template instance `code.Dice!(1u, 7u)` error instantiating
我认为这与需要能够静态解析uniform(Lo, Hi)
有关。但是我不知道如何解决这个问题。当我使用rdmd -version=variabl code.d
进行编译时,没有遇到任何问题。
对于它的价值,我的目标是能够定义一个“骰子”类型,以便我可以在其上实现范围,运算符重载等,以在D中体会到这一点。
import std.range : generate ;
import std.random : uniform ;
version(templat)
{
struct Dice(uint Lo, uint Hi)
{
auto values = generate!(() => uniform(Lo, Hi));
}
void main()
{
Dice!(1, 7) d6;
}
}
version(variabl)
{
void main()
{
auto d6a = generate!(() => uniform(1, 7));
}
}
答案 0 :(得分:1)
为了使generate!
起作用,它需要在构造第一个结果时对其进行缓存,但是设置默认的struct值是在编译时进行的。 (因此尝试使用ctfe运行uniform()...)
您可以做的就是使用这样的别名:
import std.range : take, generate;
import std.random : uniform;
import std.stdio, writeln;
alias Dice(uint Lo, uint Hi) = generate!(() => uniform(Lo, Hi));
void main()
{
auto d6 = Dice!(1, 7);
writeln(d6.front);
writeln(d6.front); // same as above because you didnt pop it
d6.popFront();
writeln(d6.front);
d6.popFront();
d6.take(3).writeln;
}
此外,这是一个不使用generate!
而直接创建范围的示例。
import std.range : take;
import std.random : uniform;
import std.stdio, writeln;
struct Dice(uint Lo, uint Hi)
{
void popFront()
{
front = uniform(Lo, Hi);
}
static bool empty = false;
uint front;
}
auto makeDice(uint Lo, uint Hi)(){
auto dice = Dice!(Lo, Hi)();
dice.popFront();
return dice;
}
void main()
{
auto d6 = makeDice!(1, 7);
writeln(d6.front);
writeln(d6.front); // same as above because you didnt pop it
d6.popFront();
writeln(d6.front);
d6.popFront();
d6.take(3).writeln;
}