Вывести параметр шаблона без типа
-
27-10-2019 - |
Вопрос
Можно ли вывести параметр шаблона без типа из параметра функции шаблона?
Рассмотрим этот простой шаблон:
template <int N> constexpr int factorial()
{
return N * factorial<N - 1>();
}
template <> constexpr int factorial<0>()
{
return 1;
}
template <> constexpr int factorial<1>()
{
return 1;
}
Я хотел бы иметь возможность изменить factorial
чтобы я мог альтернативно назвать это так:
factorial(5);
и пусть компилятор выясните значение n во время компиляции. Это возможно? Может быть, с каким -то причудливым дополнением C ++ 11?
Решение
Не может быть сделано, если у вас нет машины времени.
Параметр к функции обрабатывается во время выполнения. Да, в ваш Случай это буквальная постоянная, но это особый случай.
В определениях функции, параметр типы зафиксированы во время компиляции (и, следовательно, могут использоваться для определения параметров шаблона), но параметр ценности фиксируются только во время выполнения.
зачем вам это? Это просто так, что вам не нужно печатать <>
S?
Другие советы
Ваш текущий код обычно пишутся следующим образом, я считаю:
constexpr factorial (int n)
{
return n > 0 ? n * factorial( n - 1 ) : 1;
}
Если вы называете это с постоянной экспрессией, например factorial(5)
, Тогда все магии компилятора вступит в игру. Но если вы сделаете int a = 3; factorial(a)
, Тогда я думаю, что это вернется на обычную функцию - то есть у него не будет создан таблица поиска предварительно вычисленных ответов.
В общем, вы должны отмечать каждую функцию и конструктор как constexpr
если вы можете. Вы ничего не теряете, компилятор будет рассматривать его как нормальную функцию, если это необходимо.
Я не думаю, что вы можете это сделать; Единственный способ, которым вы могли бы сделать это, - это иметь constexpr
параметр функции, который будет передаваться тогда как template
параметр для версии шаблона factorial
, но constexpr
Параметры функции не допущены.
Нет, это невозможно, если вы не хотите создать огромный оператор Switch:
int getFactorial( const int v )
{
switch ( v )
{
case 1 : return factorial<1>();
case 2 : return factorial<2>();
//etc
default:
;
}
return 0;
}
Нет, ты не можешь этого сделать. Шаблонные аргументы могут быть выведены только из тип Функционального аргумента, а не ценность, что в целом не будет известно во время компиляции.
Конечно, вы можете переписать factorial
как неэбрат constexpr
функция; Тогда это будет оцениваться во время компиляции, если аргумент будет известен тогда.
Используйте злой макрос:
#define factorial(X) factorial<X>()