Since c++11 the c ++ standards committee has made it a goal to approve a new standard every 3 years. This has been the case to date and we have had the following standards:
Standardization is divided into four working groups:
- Nucleus (Core): Maintenance of the language and standardization of new proposals.
- Evolution : Development of new features for the language.
- Library : Maintenance of the standard library and standardization of new proposals.
- Library evolution : Development of new features for the standard library.
In July 2019, the C++20 standard was considered closed. This implies that no new features can be added (although some could be removed if problems are detected) and approved features are being reviewed for possible improvements or minor corrections.
At this last meeting, it was considered that the Contracts 2 proposal (technical document P0542R4 ) would not be incorporated in C++20 and is delayed to C++23.
We are going to list some of the main features that C++20 will incorporate.
1 Due to some strange oversight, I wrote two threads about C++17.
2 According to Wikipedia the contract is:
Design - by-contract is a methodology for the design and implementation of applications and components popularized by the Eiffel programming language . It consists of considering design elements as participants in a relationship similar to a business contract. Thus, components can be designed assuming that certain input conditions (pre-conditions) will be met, while certain output conditions (post-conditions) must be guaranteed, as well as class invariance (properties that remain invariant despite of the processing performed by the component).
C++ Contracts will follow the attribute syntax (added in C++11):
[[contrato modificador: expresión-condicional]]
Contracts have been moved to C++23, the following is subject to change: The available contracts are:
expects
: A type contractexpects
is a pre-condition. Indicates what a function expects from its arguments, and that contract is expected to hold throughout the function call.ensures
: A type contractensures
is a post-condition. Indicates the state that the objects passed to a function (or the return from it) are expected to have at the end of the call.asert
: A type contractassert
is an assertion. Indicates a condition that is expected to be satisfied where the contract appears.
When a contract is not fulfilled, a function call will be made with the following signature:
void(const std::contract_violation &);
The object std::contract_violation
will contain information about the breach of contract such as where (file, line, function) has been breached.
Modifiers can be applied to contracts, modifiers will affect how code with contracts is generated and whether or not contracts are checked at runtime. The available modifiers are:
axiom
: The verification of the conditions of this contract is expected to have no cost, it is not evaluated at execution time.default
: Verification of the conditions of this contract is expected to be inexpensive.audit
: Verification of the terms of this contract is expected to be expensive.
The contracts that will be verified at compile time contain code that will be compiled, you can specify the level with which you want to compile each translation unit and the resulting behavior will be:
- Default: Checks (compiles) contracts marked as
default
(contracts that have no modifier are considereddefault
). - Audit: Verifies (compiles) the contracts marked as
audit
anddefault
.
Nucleus.
Concepts .
Concepts are an enhancement to the C++ template system, they are a special type of compile-time evaluable function that must return true to consider the concept true. Its function is to control the characteristics that the parameters of a template must meet. But their functionality is not limited to the scope of templates, they can also be used in other contexts.
Concepts are long-awaited C++ functionality that's been 10 years in the making (it was left out of C++11 due to lack of time, left out of C++14 as incomplete, and left out of C++17 due to lack of consensus).
Example
We can define a concept as follows:
The previous concept is fulfilled if the expression
a + b
is possible and its type istipo_t
, then we can use the concept as a parameter:And the function
suma
will only accept types that satisfy the conceptes_sumable
. It can also be used as a variable:The variable
resultado
will have to matches_sumable
or the code will not compile. Lastly, a template may be required to meet one or more concepts:In the previous function, the template parameter
T
must be a 32-bit integer, if it is not, a clear and concise error will be displayed:Initializers by Name in Aggregates (DT P0329R0 )
Proposal to allow names to be specified in the initialization of objects of aggregate type, as is already allowed in C (since C99).
Example
Assuming we have the following object:
The following initialization would be correct as of C++20:
There are certain differences compared to C99 that must be taken into account:
All members must be initialized:
The members must be in the order of definition:
Members must not be duplicated:
Formation initialization is not allowed:
Nested initialization is not allowed:
Lambdas template (DT P0428R2 )
Since C++14 the language allows Generic Lambda ; but while they make C++ Lambdas more useful, Generic Lambdas don't offer as much flexibility as might be expected, to the point that in some contexts it's still more useful to use a template function rather than a Generic Lambda. This whitepaper proposes the following new syntax for Lambdas:
That is, angle brackets (
<
and>
) are added to the Lambda in order to handle template parameters.Example
Lambda that works only with
std::vector
Generic version:Template version:
Lambda that calls a static function of the passed type and accesses nested types Generic version:
Template version:
Three-way comparison (white paper P0515R3 ).
This proposal is known by the pseudonym " The spaceship operator " because of the resemblance of the proposed operator (
operator <=>
) to a Tie-Fighter:The proposal suggests adding a new operator to the language that performs a comparison between objects, being able to obtain three different results, for the three-way comparison , the following
a <=> b
would be obtained:a
it is less thanb
.a
andb
were equivalent.a
it is greater thanb
.The three-way comparison would reduce the amount of code needed to allow a data to be strictly sortable , which requires several comparisons that are usually implemented based on the previous ones to save code:
The proposal suggests allowing the compiler to generate the three-way comparison by default, doing so would perform a member-to-member three-way comparison recursively between the operators of the operator.
Example
Three-way comparison (generated by the compiler) of the object in the code above:
The return type will be
auto
because the return type is compiler dependent, the only restriction it must follow is that it can be compared against zero (greater than, less than, or equal to zero).for
range with initializer (technical document P0614R1 )In C++11 the range loop was added
for
with the following syntax:It allows you to create code that is easier to understand and maintain, but lacks the flexibility of the
for
traditional loop by not allowing initializers. The proposal is to relax the range loopfor
with an initializer:Example
We get a temporary object from which we iterate one of its internal properties:
Default Constructable and Mappable Stateless Lambdas (DT P0624R2 )
A lambda without captures is called " Lambda without state ", this type of lambda is implicitly convertible to function pointer:
Pero en algunas situaciones no se comportan como punteros a función. Los punteros a función son copiables, asignables y construibles mientras que las lambdas sin estado no lo son.
Ejemplo
Esta propuesta hace que las lambda sin estado se comporten como punteros a función:
Permitir la expansión de paquetes de parámetros en la captura de lambdas (DT P0780R0)
En una lambda se pueden capturar los parámetros por copia:
Pero el estándar previo a C++20 prohíbe explícitamente expandir paquetes de parámetros en las capturas.
Ejemplo
C++20 levanta esta prohibición:
Literales de cadena de caracteres como parámetros no-tipo en plantillas (DT P0424R2)
El estándar previo a C++20 establece explícitamente que los literales de cadena de caracteres no pueden ser usados como parámetros de plantilla:
El motivo de esta limitación es que dos literales de texto iguales (como en el ejemplo anterior) no tienen garantías de ser el mismo literal (se almacenan como punteros) y en consecuencia no hay manera de saber si dos funciones con el mismo literal de texto son la misma. En C++20 se permite la verificación del parámetro literal de texto en tiempo de compilación pudiendo comprobar si dos literales de texto tienen el mismo contenido, esto permite que los literales de texto puedan ser usados como parámetros no-tipo en plantillas.
Macros de verificación de funcionalidades (DT P0941R1)
Si el compilador dispone de una funcionalidad determinada, ésta podrá ser verificada usando la macro
__has_cpp_attribute
. La macro recibirá un único parámetro que será un identificador asociado a una funcionalidad determinada.Ejemplo
Si el compilador dispone del bucle
for
de rango (C++11) lo usamos, usamos el bucle tradicional en caso contrario:###Explícito condicional
explicit(bool)
(documento técnico P0892R2). En el estándar C++11 se permitió controlar las conversiones implícitas al construir o convertir objetos al permitir marcar como explícitos los constructores u operadores. En C++20 se amplía esta funcionalidad pudiendo pasar un parámetro al especificadorexplicit
para hacer que éste se aplique condicionalmente.Ejemplo
El objeto
O
tiene un constructor explícito cuando el tipo usado para construirlo sea de mayor tamaño que el tipo almacenado, constructor implícito en caso contrario:La palabra clave
explicit
esperará una expresión convertible a booleano a partir de C++20, así que habrá que corregir algunas líneas de código:Permitir que las llamadas a funciones virtuales sean
constexpr
(DT P1064R0)Las llamadas a funciones virtuales están prohibidas en expresiones constantes en estándares previos a C++20.
Ejemplo
El compilador conoce los tipos implicados en algunas llamadas virtuales y podría resolver la llamada en tiempo de compilación.
Funciones Inmediatas (DT P1073R2)
A partir de C++11 se puede usar la palabra clave
constexpr
para marcar valores o funciones que podrían ser válidas dentro de una expresión constante (expresión calculada en tiempo de compilación). Las funciones marcadas comoconstexpr
pueden también ser llamadas en tiempo de ejecución.Esta propuesta añade la palabra clave
consteval
para marcar valores o funciones que obligatoriamente deben ser evaluadas en tiempo de compilación y producir un error en caso contrario.Las funciones
consteval
reciben el nombre de función inmediata porque la función no se compila para ser ejecutada si no que se evalúa en tiempo de compilación y se sustituye su llamada por el resultado de la evaluación, una función inmediata no tiene por qué aparecer en el binario compilado.Ejemplo
Las funciones inmediatas provocan un error de compilación si no se pueden calcular en tiempo de compilación:
constinit
(DT P1143R2)El lenguaje C++ no especifica el orden en que las variables estáticas deben ser inicializadas, dejando esta decisión en manos de los compiladores. Esto provoca que las variables estáticas con inicializadores dinámicos provoquen errores difíciles de rastrear cuando unas dependen de otras (esto se conoce como Static Initialization Order Fiasco). Las variables con inicializadores constantes evitan este problema, ya que pueden inicializarse en tiempo de compilación y se pueden usar de manera segura para inicializar otras variables.
Para garantizar que una variable se inicializa en tiempo de compilación, se debe obligar al compilador a que la inicialización sea constante, para ello se puede marcar una con
constinit
:Ejemplo
Tenemos una función (
valor_dinamico
) que calcula un valor en tiempo de ejecución y otra (misterio
) que podría ser evaluada en tiempo de compilación o en tiempo de ejecución:Si
misterio
no puede ser evaluada en tiempo de compilación, la expresión marcada conconstinit
falla.using
enumerado (DT P1099r5)En C++11 se añadieron al lenguaje los enumerados-clase:
Este nuevo tipo de enumerado no exporta sus símbolos al ámbito superior:
Ejemplo
A partir de C++20 se permite importar los símbolos de un enumerado-clase mediante la cláusula
using
:Permitir conversiones a formaciones abiertas (DT P0388R4)
WIP.
Funciones miembro especiales condicionalmente triviales (DT P0848R3)
WIP.
Parcheando la deducción de parámetros plantilla de clase (DT P1021R5)
WIP.
Deprecar
volatile
(DT P1152R4)WIP.
Librería.
Extender
<chrono>
para manejar calendarios y zonas horarias (DT P0355R7).Se incorpora a la librería de manejo de tiempo
Ejemplo.<chrono>
utilidades para manejar calendarios y zonas horarias:Conversión estándar a bits (documento técnico P0476R2).
En programación a bajo nivel, suele ser necesario interpretar un dato como si fuera otro; en otras palabras: mantener la misma representación binaria pero obteniendo un dato de diferente tipo.
Normalmente se usa
reinterpret_cast
o type punning mediante uniones para conseguirlo, pero éstos métodos son propensos a errores, lo más seguro es usar unstd::aligned_storage
sobre el que copiar los datos, pero es incómodo y costoso.La nueva cabecera
<bit>
proporciona herramientas para acceder, manipular y procesar tanto secuencias de bits como bits individuales de una forma menos propensa a errores y más flexible: asegura que los tamaños de los tipos de entrada y de salida coincidan, garantiza que ambos tipos sean copiables y hace que la expresión se calcule en tiempo de compilación cuando sea posible.Librería de formato de texto (DT P0645R10).
Las herramientas de escritura de texto de C++ son difíciles de entender y usar, el encadenado de
Ejemplo.std::ostream
y los formateos de<iomanip>
en ocasiones se quedan cortos y no ofrecen una suficiente flexibilidad, en ocasiones se delega aprintf
por claridad o costumbre. Este documento técnico propone una alternativa a el formateo de texto con la flexibilidad deprintf
y la seguridad destd::ostream
.La librería de formato de texto acepta argumentos posicionales implícitos y explícitos:
Constantes matemáticas (DT P0631R8).
Este documento técnico propone una nueva cabecera
<numbers>
y espacio de nombresnumbers
. Se incluyen varias constantes matemáticas de uso común como e, π, inversa de π… en formato de variable plantilla:Sufijos para
ptrdiff_t
ysize_t
(DT P0330R3)El siguiente código provoca un error de compilación:
La variable
i
se deduce comoint
mientras quef
se deduce como el retorno destd::vector::size
(que suele definirse comostd::size_t
), el siguiente código corrige el problema:Pero pierde flexibilidad. Dado que no existen literales de tipo
Ejemplo.std::size_t
se propone un sufijo:El sufijo
zu
(siz
eu
nsigned) soluciona el problema:Evolución.
Excepciones determinísticas sin coste:
throw
valores (DT P0709R4)WIP.
using
de enumerado (DT P1099R5)WIP.
Soporte a la configuración de clases (DT P1112R2)
WIP.
constinit
(DT P1143R2)WIP.
Añadir texto informativo a
[[nodiscard]]
(DT P1301R4)WIP.
Evolución de librería.
Integrar simd con algoritmos paralelos (DT P0350R3)
WIP.
Hacer que
std::string
ystd::vector
seanconstexpr
(DT P0980R1 y P1004R2)WIP.
Librería de Conceptos (documento técnico P0898R2).
Los conceptos serán una herramienta de C++ para hacer verificaciones sobre los tipos de los parámetros en tiempo de compilación. Es una utilidad que se lleva desarrollando desde C++11 y aunque aún no ha sido incorporada al lenguaje hay varios compiladores que le dan soporte, lo que hace pensar que será aprobada en breve. Para evitar desarrollar conceptos desde cero se propone una librería de conceptos que ofrezca los más comunes.
Ejemplo.
Usamos el concepto
Copyable
para que una función sólo acepte tipos que se puedan copiar:Clases como parámetros no-tipo en plantillas (documento técnico P0732R2).
C++ sólo permite datos que puedan ser evaluados en tiempo de compilación para verificar su unicidad como argumentos para parámetros no-tipo en plantillas. Esto limita el tipo de estos parámetros a enteros y punteros o referencias a datos o funciones con enlazado externo.
En otras palabras, se necesita garantizar que dada una plantilla con parámetro no-tipo, tiene que ser cierto que
&P<a> == &P<b>
cuandoa == b
, pero las clases de C++ no son por defecto comparables por igualdad ni el operador de igualdad forma parte de las funciones especiales que auto-genera el compilador. Así que este documento técnico propone usar el operador de comparación a tres bandas (apodado operador nave espacial<=>
) ya que se ha propuesto que éste si sea auto-generado por el compilador.Ejemplo.
Este código sería válido en C++20 pero no lo sería en estándares anteriores:
Reflexión estática (documento técnico P0275R4).
Según la Wikipedia, la reflexión es:
Este documento técnico propone añadir utilidades de reflexión a C++, esta reflexión sería estática (disponible en tiempo de compilación), para ello se añadiría al lenguaje la palabra clave
reflexpr
que aplicada sobre una definición, devolverá un objeto que contenga información de la misma.Ejemplo.
Podemos obtener el nombre de un parámetro así:
Usar
[[nodiscard]]
en la librería estándar (documento técnico P0600R1).Este documento técnico propone añadir el atributo
[[nodiscard]]
en la librería estándar cuando no usar el valor de retorno:De momento se valora marcar como
[[nodiscard]]
std::async()
,std::launder
,std::allocate
yempty
en contenedores.Flujo de salida con sincronización (documento técnico P0053R7).
El estándar garantiza que los flujos de salida de datos no producirán condiciones de carrera, pero no garantiza que enviar datos a esos flujos produzca un efecto perceptible; para que esto sea así se requiere un mecanismo de sincronización.
Este documento técnico propone añadir al estándar
basic_osyncstream
que envuelva un flujo de datos al que transferirá datos cuando se llame su destructor, de esta manera garantiza que los datos se envíen al flujo incluso en presencia de una excepción.Ejemplo.
Constantes matemáticas estandarizadas (documento técnico P0631R5).
Las constantes matemáticas como π y e son usadas frecuentemente en algoritmos pero no existe una definición de las mismas en ninguna cabecera estandarizada. Son muy fáciles de definir, pero es tan extraño como hacer una reserva en un restaurante en el que te piden que traigas tu propio salero.
Para suplir esta carencia, este documento técnico propone crear una colección de variables plantilla con los valores de las constantes más usadas, por citar algunas:
Ejemplo.
Con tan sólo incluir la cabecera
<math>
podremos usar estas constantes:Co-rutinas (documento técnico N3985).
Según la Wikipedia una co-rutina es:
Several programming languages support coroutines natively, this document proposes to make coroutines part of the C++ standard.