Whyever * * not * * declare a function to be `constexpr`?
Cualquier función que consista en una sentencia return solo puede ser declarada
constexpr
y por lo tanto permitirá ser evaluado en tiempo de compilación si todos
los argumentos son constexpr
y solo las funciones constexpr
son llamadas en su
cuerpo. ¿Hay alguna razón para no declarar cualquier tal función constexpr
?
Ejemplo:
constexpr int sum(int x, int y) { return x + y; }
constexpr i = 10;
static_assert(sum(i, 13) == 23, "sum correct");
¿Podría alguien proporcionar un ejemplo donde declarar una función constexpr
¿haría algún daño?
Alguna inicial pensamientos:
Incluso si no debería haber una buena razón para declarar una función
no constexpr
Podría imaginar que la palabra clave constexpr
tiene un
función de transición: su ausencia en el código que no necesita tiempo de compilación
las evaluaciones permitirían a los compiladores que no implementan el tiempo de compilación
evaluaciones todavía para compilar ese código (pero para fallar confiablemente en el código
que los necesita como se hace explícito mediante el uso de constexpr
).
Pero lo que no entiendo: si no debe haber una buena razón para
nunca declarando una función no constexpr
, ¿por qué no es cada función
en la biblioteca estándar declarada constexpr
? (No puedes discutir
que aún no se ha hecho porque todavía no había tiempo suficiente para
hacerlo, porque hacerlo para todos es una obviedad contrary contrario a decidir
para cada función si hacerlo constexpr
o no.)
--- Soy consciente de que N2976
deliberadamente no requiere cstrs para muchos tipos de biblioteca estándar tales
como los contenedores como esto sería demasiado limitante para posible
aplicación. Vamos a excluirlos del argumento y solo preguntarse:
una vez que un tipo en la biblioteca estándar realmente tiene un constexpr
cstr, ¿por qué no
cada función que opera en él declaró constexpr
?
En la mayoría de los casos tampoco puede argumentar que puede preferir no declarar una función
constexpr
simplemente porque no prevé ningún uso en tiempo de compilación:
porque si otros evtl. usarán su código, pueden ver tal uso que
no. (Pero concedido para tipos de rasgos y cosas por igual, por supuesto.)
Así que supongo que debe haber una buena razón y un buen ejemplo para deliberadamente
no declarar una función constexpr
?
(con "cada función" siempre quiero decir: cada función que cumple con el
requisitos para ser constexpr
, es decir, se define como un único
return, toma solo argumentos de tipos con constexpr
cstrs y solo llama a funciones constexpr
.)
La pregunta ¿por Qué std::forward
descartar constexpr
-ness?
es un caso especial de este.
3 answers
Las funciones solo se pueden declarar constexpr
si obedecen las reglas de constexpr
- - - no hay casts dinámicos, no hay asignación de memoria, no hay llamadas a funciones no-constexpr
, etc.
Declarar una función en la biblioteca estándar como constexpr
requiere que TODAS las implementaciones obedezcan esas reglas.
En primer lugar, esto requiere comprobar para cada función que puede ser implementado como constexpr
, que es un trabajo largo.
En segundo lugar, esta es una gran restricción en las implementaciones, y prohibirá muchas depuración de implementaciones. Por lo tanto, solo vale la pena si los beneficios superan los costos, o los requisitos son lo suficientemente ajustados como para que la implementación tenga que obedecer las reglas constexpr
de todos modos. Hacer esta evaluación para cada función es de nuevo un trabajo largo.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-25 10:59:16
Creo que a lo que se refiere se llama evaluación parcial. Lo que estás tocando es que algunos programas se pueden dividir en dos partes - una pieza que requiere información de tiempo de ejecución, y una pieza que se puede hacer sin ninguna información de tiempo de ejecución - y que en teoría se podría evaluar completamente la parte del programa que no necesita ninguna información de tiempo de ejecución antes de empezar a ejecutar el programa. Hay algunos lenguajes de programación que hacen esto. Por ejemplo, la D el lenguaje de programación tiene un intérprete integrado en el compilador que le permite ejecutar código en tiempo de compilación, siempre que cumpla con ciertas restricciones.
Hay algunos desafíos principales para conseguir que la evaluación parcial funcione. Primero, complica dramáticamente la lógica del compilador porque el compilador necesitará tener la capacidad de simular todas las operaciones que usted podría poner en un programa ejecutable en tiempo de compilación. Esto, en el peor de los casos, requiere que tenga una completa intérprete dentro del compilador, haciendo un problema difícil (escribir un buen compilador de C++) y haciéndolo órdenes de magnitud más difícil de hacer.
Creo que la razón de la especificación actual sobre constexpr
es simplemente limitar la complejidad de los compiladores. Los casos a los que se limita son bastante fáciles de verificar. No hay necesidad de implementar bucles en el compilador (lo que podría causar toda una serie de problemas, como lo que sucede si obtiene un bucle infinito dentro del compilador). Se también evita que el compilador potencialmente tenga que evaluar sentencias que podrían causar segfaults en tiempo de ejecución, como seguir un mal puntero.
Otra consideración a tener en cuenta es que algunas funciones tienen efectos secundarios, como leer desde cin
o abrir una conexión de red. Funciones como estas fundamentalmente no se pueden optimizar en tiempo de compilación, ya que hacerlo requeriría conocimiento solo disponible en tiempo de ejecución.
Para resumir, no hay ninguna razón teórica por la que no puedas evaluar parcialmente los programas C++ en tiempo de compilación. De hecho, la gente hace esto todo el tiempo. Los compiladores de optimización, por ejemplo, son esencialmente programas que tratan de hacer esto tanto como sea posible. La metaprogramación de plantillas es una instancia en la que los programadores de C++ intentan ejecutar código dentro del compilador, y es posible hacer algunas cosas geniales con plantillas en parte porque las reglas para las plantillas forman un lenguaje funcional, que el compilador tiene un tiempo más fácil de implementar. Por otra parte, si usted piensa de la compensación entre las horas de autor del compilador y las horas de programación, la metaprogramación de plantillas muestra que si está bien hacer que los programadores hagan lo imposible para obtener lo que quieren, puede construir un lenguaje bastante débil (el sistema de plantillas) y mantener la complejidad del lenguaje simple. (Digo " débil "como en" no particularmente expresivo", no" débil " en el sentido de la teoría de la computabilidad).
Espero que esto ayude!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-25 08:51:11
Si la función tiene efectos secundarios, no querrá marcarla constexpr
. Ejemplo
No puedo obtener ningún resultado inesperado de eso, en realidad parece que gcc 4.5.1 simplemente ignora constexpr
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-25 05:15:41