Static Parameter Function Specialization in D

Xinok xinok at live.com
Mon Nov 11 06:39:54 PST 2013


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.


More information about the Digitalmars-d-announce mailing list