Static Parameter Function Specialization in D

"Nordlöw" per.nordlow at gmail.com
Mon Nov 11 05:41:03 PST 2013


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


More information about the Digitalmars-d-announce mailing list