2013-11-11 7 views
1

Я где-то читал, что D поддерживает специализацию функций для вызовов, где аргументы являются константами времени компиляции. Типичное использование этого в матричных силовых функциях (если показатель составляет 2 x*x, часто быстрее, чем в общем случае).Специализация по статическому параметру в D

Я хочу это в моей функции члена

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) 

Должен ли я сделать параметр i параметр шаблона, скажем, используя тип U, а затем использовать статический, если 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; 
} 

ответ

2

То, что вы пытаетесь сделать, на самом деле не работает. Вы можете сделать параметр значения шаблона:

void foo(int i)() { /* use i at compile time */ } 

, но тогда вы не можете передать значение времени выполнения для него, и он имеет другой синтаксис вызова: Foo 2 против обув (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. 

Внутри функции есть волшебный if(__ctfe) { running at compile time } else { at runtime}, но опять же, это не если есть буквальный, то есть, если функция выполняется в контекст CT, например, присвоение результата константе перечисления.

Но, в противном случае, int literal по-прежнему является изменяемым int до функции. Поэтому то, что вы конкретно пытаетесь сделать, не будет работать в D, как сейчас. (Были некоторые разговоры о том, чтобы узнать, является ли это буквальным, но, насколько мне известно, на самом деле нет плана на самом деле.)

+0

Ok. Я могу рассчитывать на индексацию, используя, например, 'bitset.at! 3()'. Спасибо. –

 Смежные вопросы

  • Нет связанных вопросов^_^