1

我在某处读到 D 支持将函数专门化为参数是编译时常量的调用。它的典型用途是在矩阵幂函数中(如果指数为 2 x*x,通常比一般情况快)。

我想要这个在我的成员函数中

   bool opIndexAssign(bool b, size_t i) @trusted pure nothrow in {
        assert(i < len);        // TODO: Add static assert(i < len) when i is constant
    } body {
        b ? bts(ptr, i) : btr(ptr, i);
        return b;
    }

BitSet我正在写一个静态大小的结构。这是为了在可能的情况下对索引变量进行编译时边界检查i。我想

bool opIndexAssign(bool b, const size_t i) @trusted pure nothrow in {
    static assert(i < len);
} body {
    b ? bts(ptr, i) : btr(ptr, i);
    return b;
}

就足够了,但随后 DMD 抱怨如下

dmd -debug -gc -gs -unittest -D -Dd/home/per/.emacs.d/auto-builds/dmd/Debug-Boundscheck-Unittest/home/per/Work/justd/ -w -main  ~/Work/justd/bitset.d /home/per/Work/justd/assert_ex.d -of/home/per/.emacs.d/auto-builds/dmd/Debug-Boundscheck-Unittest/home/per/Work/justd/bitset
/home/per/Work/justd/bitset.d(58): Error: bitset.BitSet!2.BitSet.opIndexAssign called with argument types (bool, int) matches both:
    /home/per/Work/justd/bitset.d(49): opIndexAssign(bool b, ulong i)
and:
    /home/per/Work/justd/bitset.d(65): opIndexAssign(bool b, const(ulong) i)
/home/per/Work/justd/bitset.d(66): Error: variable i cannot be read at compile time
/home/per/Work/justd/bitset.d(66):        while evaluating: static assert(i < 2LU)
/home/per/Work/justd/bitset.d(58): Error: bitset.BitSet!2.BitSet.opIndexAssign called with argument types (bool, int) matches both:
    /home/per/Work/justd/bitset.d(49): opIndexAssign(bool b, ulong i)

我是否必须将参数设为i模板参数,例如使用 type U,然后使用 static if someTypeTrait!U。我试过这个,但 isMutable!Index 总是评估为真。

import std.traits: isIntegral;
bool opIndexAssign(Index)(bool b, Index i) @trusted pure nothrow if (isIntegral!Index) in {
    import std.traits: isMutable;
    // See also: http://stackoverflow.com/questions/19906516/static-parameter-function-specialization-in-d
    static if (isMutable!Index) {
        assert(i < len);
    } else {
        import std.conv: to;
        static assert(i < len,
                      "Index " ~ to!string(i) ~ " must be smaller than BitSet length " ~  to!string(len));
    }
} body {
    b ? bts(ptr, i) : btr(ptr, i);
    return b;
}
4

1 回答 1

2

你试图做的事情并没有真正奏效。你可以做一个模板值参数:

void foo(int i)() { /* use i at compile time */ }

但是您不能将运行时值传递给它,并且它具有不同的调用语法:foo!2 vs foo(2)。

最接近的是 CTFE:

int foo(int i) { return i; }
enum something = foo(2); // works, evaluated at compile time
int s = foo(2); // also works, but runs at runtime.

在函数内部,有一个魔术if(__ctfe) { running at compile time } else { at runtime},但同样,这不是如果有文字,而是如果函数在 CT 上下文中运行,例如,将结果分配给枚举常量。

但是,否则,就函数而言,int 文字仍然是可变的 int。因此,您具体尝试做的事情不会像现在这样在 D 中起作用。(有人谈论想要一种方法来判断它是否是文字,但据我所知,没有计划真正做到这一点。)

于 2013-11-12T01:31:44.763 回答