On Monday, 11 November 2013 at 13:41:04 UTC, Nordlöw wrote:
I've read somewhere that D supports specialization of functions to calls where arguments are compile-time constants. Typical use of this is in matrix power functions (if exponent is 2 `x*x` is often faster than the general case).


I want this in my member function

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;
        }

of a statically sized `BitSet` struct I'm writing. This in order to, when possible, get compile-time bounds checking on the index variable `i`. I thought

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;
    }

would suffice but then DMD complains as follows

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)

Do I have to make parameter `i` a template parameter, say using type `U`, and then use static if `someTypeTrait!U`. I tried this but isMutable!Index always evaluates to 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;
    }

It's possible that the compiler can inline the function and optimize the code from there, but I don't know of any language feature that can do this explicitly.

Reply via email to