utiliza una tipos que parametros maximo internas función funciones funcion externas entero definir con codigo clases c++ c++11 constexpr

c++ - una - Parámetros de la función constexpr como argumentos de plantilla



funciones void c++ (4)

El compilador no sabe si xey siempre están disponibles en tiempo de compilación como valores constantes (expresión), y qué más, C ++ 11/14 no admite el parámetro de función constexpr , por lo que no hay forma de que x e y puedan usarse como parámetro para la plantilla agregar <> en addFunc.

Estoy jugando con un código de juguete usando c ++ 11 para descubrir un poco más sobre cómo funcionan las cosas. Durante esto encontré el siguiente problema que se simplifica a:

template <int x, int y> class add { public: static constexpr int ret = x + y; }; constexpr int addFunc(const int x, const int y) { return add<x,y>::ret; } int main() { const int x = 1; const int y = 2; cout << add<x,y>::ret << endl; // Works cout << addFunc(1,2) << endl; // Compiler error return 0; }

Estoy usando GCC 4.8.1 y la salida es:
''x'' no es una expresión constante en el argumento de plantilla para el tipo ''int''
''y'' no es una expresión constante en el argumento de la plantilla para el tipo ''int''

¿Cuál es exactamente la diferencia entre las dos formas en las que estoy tratando de calcular add::ret ? Ambos valores deberían estar disponibles en tiempo de compilación.


Le dices al compilador que addFunc sería un constexpr. Pero depende de los parámetros, que no son constexpr en sí, por lo que el compilador ya se ahoga con eso. Marcarlos como constantes solo significa que no los va a modificar en el cuerpo de la función, y las llamadas específicas que realiza a la función no se consideran en este momento.

Hay una manera de hacer que el compilador entienda que solo va a pasar constantes de tiempo de compilación para addFunc : Convierta los parámetros en parámetros de una plantilla en sí:

template <int x, int y> constexpr int addFunc() { return add<x,y>::ret; }

Entonces llama como

cout << addFunc<1,2>() << endl;


Los parámetros de función de una función constexpr no son expresiones constantes. La función es constexpr hacia el exterior (ya que llamarla puede resultar en una expresión constante), pero los cálculos internos son tan constexpr como lo serían en una función normal.

Los argumentos de plantilla requieren expresiones constantes. Estos son los requisitos cruciales para las expresiones constantes que no se cumplen en su código y, por lo tanto, producen el error del compilador ([expr.const] / 2, énfasis mío):

Una expresión condicional es una expresión constante central a menos que incluya uno de los siguientes como una subexpresión potencialmente evaluada (3.2) [...]:

- una conversión de lvalue a rvalue (4.1) a menos que se aplique a

  • un valor de tipo integral o de enumeración que hace referencia a un objeto const no volátil con una inicialización anterior, inicializado con una expresión constante, o
  • un valor de tipo literal que se refiere a un objeto no volátil definido con constexpr , o que se refiere a un subobjeto de tal objeto, o
  • un valor de tipo literal que hace referencia a un objeto temporal no volátil cuyo tiempo de vida no ha finalizado, inicializado con una expresión constante;

Está aplicando una conversión de lvalue a rvalue en los parámetros para pasarlos como argumentos de plantilla.
El primer elemento con viñeta no se aplica, ya que el parámetro de función no se ha iniciado previamente ni se sabe que se inicialice con una expresión constante, y el segundo y el tercero tampoco (en particular, los parámetros de función no se declararán constexpr )


Si su propósito es acortar un poco el código, en C ++ 14 puede crear una plantilla variable:

template <int x, int y> constexpr int addVar = x + y; cout << addVar<5, 6> << endl; // Works with clang 3.5, fails on GCC 4.9.1

GCC 5 también apoyará esto .