1

D は、引数がコンパイル時の定数である呼び出しへの関数の特殊化をサポートしていることをどこかで読みました。これの典型的な使用法は、行列ベキ関数です (指数が 2x*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)

type を使用してパラメーターiをテンプレートパラメーターにしU、次に static if を使用する必要がありますかsomeTypeTrait!U。これを試してみましたが、isMutable!Index は常に true と評価されます。

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 と 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.

関数内には magic がありますがif(__ctfe) { running at compile time } else { at runtime}、これはリテラルがある場合ではなく、関数が CT コンテキストで実行される場合 (たとえば、結果を列挙型定数に代入する場合) に当てはまります。

しかし、それ以外の場合、関数に関する限り、int リテラルは変更可能な int のままです。したがって、あなたが具体的にやろうとしていることは、現在のように D では機能しません。(それがリテラルかどうかを見分ける方法が欲しいという話がいくつかありましたが、私の知る限り、実際にそれを行う予定はありません。)

于 2013-11-12T01:31:44.763 に答える