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.