无法使用Range初始化D结构成员

时间:2018-06-29 01:47:52

标签: d

我试图学习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));
}
}

1 个答案:

答案 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;

}