vuelve seguir puedo pueden problema porque poner permite los intentarlo hashtags guardaron funcionan cuantos cambios aparezco c++ algorithm c++14 constexpr

c++ - pueden - porque no puedo seguir hashtag en instagram



¿Por qué no son constexpr std:: algorithms y cuál podría ser? (5)

Este es el tema de la propuesta de Antony Polukhin P0202:

Agregar modificadores Constexpr a funciones en y encabezados

que espero sea adoptado por el Grupo de Trabajo de Evolución de la Biblioteca C ++ y llegue a C ++ 20.

¿Por qué no son constexpr métodos std::algorithm ? Si entiendo las nuevas reglas de C ++ 14 correctamente, muchos de estos métodos podrían ser constexpr . Por ejemplo, ¿por qué no se puede std::find ser constexpr ?

static constexpr std::array<char, 4> DnaBases {''A'', ''C'', ''G'', ''T''}; constexpr bool is_dna(char b) { return std::find(std::cbegin(DnaBases), std::cend(DnaBases), b) != std::cend(DnaBases); // why not? }

¿Qué otro std::algorithm s podría ser constexpr ?


La biblioteca estándar actual (C ++ 14) está bastante constexpr respecto a las capacidades correspondientes del lenguaje central con respecto a constexpr .

Por ejemplo, MSVC 2015, que solo tiene soporte de lenguaje C ++ 11 para constexpr , podría implementar casi por completo el uso completo de la biblioteca estándar de C ++ 14 de constexpr . Las únicas excepciones fueron std::min , std::max , std::minmax , std::min_element , std::max_element , std::minmax_element para std::initializer_list .

A partir de C ++ 1z (17?), std::xxx_element algoritmos std::xxx_element se convertirán en algoritmos constexpr para iterador general y entradas de comparador para unificar el uso de std::initializer_list . Además, hay propuestas para funciones constexpr lambda para C ++ 1z también.

Con la actualización de las lambdas, aún quedan algunas limitaciones básicas del lenguaje para evitar que todo el encabezado <algorithm> convierta en constexpr . (Tenga en cuenta que estos no son obstáculos tecnológicos fundamentales, la mayoría de ellos podrían resolverse permitiendo que el compilador los evalúe).

  1. Algunos algoritmos pueden asignar dinámicamente memoria llamando a std::get_temporary_buffer ( std::inplace_merge , std::stable_sort y std::stable_partition ) que no está permitido en contextos constexpr .
  2. Algunos algoritmos pueden recurrir a rutinas de C de bajo nivel como memset ( std::fill y std::fill_n ) que evitarían que los autores de bibliotecas usen estos algoritmos en contextos constexpr .
  3. Algunas implementaciones de algoritmos pueden beneficiarse del uso juicioso de goto (por ejemplo, std::nth_element , std::stable_sort ), para lo cual se rechazó una propuesta de C++1z .
  4. Por último, pero no menos importante, constexpr es un cambio de interfaz, que promete que todas las implementaciones futuras tendrán que cumplir esta promesa. Por ese motivo, las implementaciones no pueden agregar constexpr como una característica de Calidad de implementación (en contraste con noexcept ).

Especialmente el 4to problema detiene la experimentación de cuánto se podría constexpr para la biblioteca estándar (algoritmos, contenedores y otras utilidades). En su lugar, se debe escribir y aprobar una propuesta por separado para cada expansión de constexpr .


Las funciones no pueden sobrecargarse en base a constexpr . Como resultado, cualquier función definida como constexpr debe implementarse en una forma que pueda ser un constexpr . Este requisito impone restricciones en todas las implementaciones.

La especificación de C ++ 14 es algo relajada con respecto a las restricciones en comparación con C ++ 11. Sin embargo, cuando se finalizó la especificación, nadie confiaba en que todas las optimizaciones que se pueden lograr sin la restricción constexpr se pueden lograr cuando los algoritmos tienen la obligación de ser constexpr . Sin saber que la funcionalidad no constexpr no se ve obstaculizada por el mandato de implementaciones constexpr , los algoritmos no se definirán como constexpr . Se constexpr uso no constexpr de algoritmos es el uso principal de los algoritmos.

Puede valer la pena tener un conjunto especial de algoritmos que se definen como constexpr . No estoy al tanto de una propuesta correspondiente. Tampoco veo mucho si la demanda justifica la estandarización, pero mi percepción puede ser diferente de la de otros.


Puede ser constexpr , pero no puede evaluarse como una expresión constante, ya que en este caso, por ejemplo, para la búsqueda en tiempo de compilación se requiere que: begin/end sea ​​constexpr, el * operator del iterador sea constexpr, operator == debe ser constexpr, operator != para el iterador debe ser constexpr, operator ++ para el iterador debe ser constexpr. Pero, si todas las funciones son constexpr , entonces muchos algoritmos se pueden implementar con constexpr .

Puede consultar la biblioteca SPROUT para la implementación de contenedores / algoritmos constexpr.

Y charla relacionada en los foros de isocpp.org


std::algorithm algoritmo actúan sobre los iteradores. Hay una razón técnica por la que hacerlos constexpr generalmente evitaría la compilación (en C ++ 11) o no haría nada (en C ++ 14 o con constexpr condicional), pero también hay una razón semántica por la que no sería posible. sentido para ellos ser constexpr .

La razón técnica es que constexpr funciones constexpr no pueden llamar expresiones no constexpr . ForEveR señala que las funciones constexpr plantilla no pueden evaluarse en tiempo de compilación si llaman expresiones no constexpr .

En el caso de std::algorithm , la evaluación de constexpr funciones constexpr en std::algorithm requerirá que las funciones para acceder a los iteradores de contenedores sean constexpr , lo que a su vez requeriría que los iteradores mismos sean tipos constexpr . Pero esto es imposible casi por definición; los contenedores normalmente se diseñan como un acceso ligero a la memoria asignada en el montón, pero la memoria del montón no se puede asignar en tiempo de compilación (por supuesto). En los comentarios a continuación, dyp señala que los iteradores no siempre apuntan a los contenedores, pero es improbable que incluso estos iteradores puedan usarse en tiempo de compilación; por ejemplo, los objetos de flujo no son legibles ni grabables en el momento de la compilación, ya que IO no se puede realizar en el momento de la compilación.

Esto lleva al problema semántico: constexpr semánticamente significa que una función está destinada a ser posible evaluar en tiempo de compilación. Declarar funciones condicionalmente constexpr cuando es imposible evaluarlas en tiempo de compilación haría que la API fuera confusa y engañosa.

Ahora, creo que el lenguaje se mejoraría si hubiera una forma de crear y usar contenedores en tiempo de compilación; Esto haría que constexpr mucho más similar a las capacidades macro de Lisp. Eventualmente, esto puede agregarse, pero actualmente no es realmente compatible con el código de biblioteca estándar existente. El enfoque más flexible, de permitir que algunos objetos vivan en el montón durante el tiempo de compilación , es, como se mencionó anteriormente, no está soportado en absoluto por el lenguaje central, y crearía algunas complicaciones graves. Por ejemplo, ¿qué sería legal hacer con tales objetos? O bien sus vidas tendrían que limitarse solo al tiempo de compilación, o deberían incluirse como memoria estática const en el programa final (como un literal de cadena), o ... ¿qué?