Вывод аргумента шаблона в D - PullRequest
3 голосов
/ 06 марта 2012

Я пишу некоторые векторные функции, которые работают со статическими массивами D, например:

real[N] unit(uint N)(real[N] v) {
    real[N] u = (v[] / norm(v)); //explicit type necessary to force slice-operator
    return u;                    //to return static-length array
}

real[3] v = unit!(3)([1,2,3]);   //works
real[3] w = unit([1,2,3]);       //error, compiler doesn't infer the template parameter
real[3] x = [1,2,3];
auto i = unit(x);                //also works, forces statically allocated array

Итак, мой вопрос: есть ли способ заставить компилятор выводить параметр шаблона N, если я передаю буквенный массив непосредственно в функцию? Я попытался использовать формат "1.0L", в надежде, что массив был приведен из статического массива int или float, но это тоже не сработало. TL; DR Можно ли заставить средний пример (w) выше работать? Спасибо!

Edit: просто чтобы уточнить, я пробовал несколько вариантов со специализированными параметрами шаблона, но я не уверен, что сделал это правильно. Я также попытался в вызове new real[3]([1,2,3]) заставить статический массив, выделенный для кучи (единорог с тремя рогами?), Но не смог заставить его скомпилировать.

Ответы [ 2 ]

3 голосов
/ 06 марта 2012

Проблема в том, что [1,2,3] не является статическим массивом. Это динамический массив, поэтому он не может соответствовать. Это неправильный тип, и нет никакого способа иметь литерал статического массива. Если вы хотите передать литерал массива как статический массив, вам нужно либо сначала присвоить его переменной, либо привести его к нужному типу.

auto w = unit(cast(real[3])[1,2,3]);

должно работать. Лично я бы сказал, что лучше всего просто явно создать экземпляр шаблона

auto w = unit!3([1, 2, 3]);

потому что это исключает риск испортить гипс.

Теперь, я думаю, что есть определенный аргумент, что компилятор должен просто работать в этом случае, но он имеет тенденцию быть намного более требовательным к шаблонам, чем к обычным функциям, поскольку он обычно создает шаблоны с точным типом, который вы передаете без пытаясь сделать какие-либо неявные преобразования, тогда как нормальная функция неявно преобразует динамический массив в статический Не стесняйтесь открыть запрос на улучшение . Поведение может измениться. Это было недавно изменено, так что IFTI (неявная реализация шаблона функции) инстанцируется с хвостовой версией массива (например, immutable(char)[] вместо immutable(char[])), что является определенным улучшением. Теперь это немного отличается от попытки преобразования (я считаю, что компилятор просто автоматически всегда обрабатывает массивы как хвостовую константу для IFTI), поэтому я не знаю, что шансы на изменение поведения компилятора в этом случае очень велики высоко. Но спрашивать не больно.

2 голосов
/ 06 марта 2012

Idea / хак:

real[T.length] unit(T...)(T t)
{
    real[T.length] v,u;
    foreach(i,x; t) v[i] = x;
    u[] = (v[] / norm(v));
    return u;
}

void main()
{
    real[3] v = unit(1,2,3);
}

Может быть, не так быстро, как при использовании real[3] v = unit!3([1,2,3]) из-за foreach, хотя, я полагаю. Также args конвертируется в real во время выполнения. Hm.

...