Deducir el parámetro de plantilla no de tipo
-
27-10-2019 - |
Pregunta
¿Es posible deducir un parámetro de plantilla no tipo de tipo de un parámetro de función de plantilla?
Considere esta plantilla simple:
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;
}
Me gustaría poder cambiar factorial
para que alternativamente pueda llamarlo así:
factorial(5);
y deje que el compilador descubra el valor de N en el tiempo de compilación. es posible? ¿Quizás con una adición de C ++ 11 elegante?
Solución
No se puede hacer, a menos que tenga una máquina del tiempo.
El parámetro a la función se maneja en tiempo de ejecución. Si en su Caso Es una constante literal, pero ese es un caso especial.
En definiciones de funciones, el parámetro tipos se fijan en el tiempo de compilación (y por lo tanto, se pueden usar para deducir los parámetros de la plantilla), pero el parámetro valores solo se fijan en tiempo de ejecución.
¿Por qué necesitas esto? ¿Es solo para que no tengas que escribir el <>
'¿s?
Otros consejos
Creo que su código actual se escribiría de la siguiente manera:
constexpr factorial (int n)
{
return n > 0 ? n * factorial( n - 1 ) : 1;
}
Si lo llama con una expresión constante, como factorial(5)
, entonces toda la magia del compilador entrará en juego. Pero si lo haces int a = 3; factorial(a)
, entonces creo que recurrirá a una función convencional, es decir, no habrá construido una tabla de búsqueda de respuestas precomputadas.
En general, debe marcar todas las funciones y constructor como constexpr
si puedes. No pierdes nada, el compilador lo tratará como una función normal si es necesario.
No creo que puedas hacer eso; La única forma en que podrías hacer eso sería tener un constexpr
parámetro de función que se pasaría entonces como el template
Parámetro para la versión de plantilla de factorial
, pero constexpr
Los parámetros de la función no se admiten.
No, no es posible, a menos que desee crear una gran declaración de cambio:
int getFactorial( const int v )
{
switch ( v )
{
case 1 : return factorial<1>();
case 2 : return factorial<2>();
//etc
default:
;
}
return 0;
}
No, no puedes hacer eso. Los argumentos de la plantilla solo se pueden deducir de la escribe de argumento de función, no el valor, que en general no se conocerá en el momento de la compilación.
Por supuesto, podrías reescribir factorial
como un no plantilla constexpr
función; entonces se evaluaría en el momento de la compilación si se conoce el argumento.
Usa una macro malvada:
#define factorial(X) factorial<X>()