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?

¿Fue útil?

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>()
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top