C++20

La versión actual de la página aún no ha sido revisada por colaboradores experimentados y puede diferir significativamente de la versión revisada el 17 de enero de 2022; las comprobaciones requieren 135 ediciones .

C++20  es el nombre del estándar ISO /IEC para el lenguaje de programación C++ . La especificación se publicó en diciembre de 2020 [1] .

El Comité de estándares de C++ comenzó a planificar C++20 en julio de 2017 [2] . C++20 es el sucesor de C++17 .

La constante ha aumentado a . __cplusplus202002L

Prohibido y eliminado

Las operaciones con volátiles están prohibidas

El modificador obviamente depende de la máquina, para comunicarse con el equipo. Por lo tanto, no está claro cuál es la semántica de esta o aquella operación y cuántos accesos a la memoria habrá. Para la sincronización entre subprocesos, es mejor usar . volatileatomic

Las siguientes operaciones con -variables están prohibidas [3] : volatile

atomicSe han agregado características adicionales para compensar lo que estaba prohibido .

Se eliminó la inicialización agregada cuando hay un constructor personalizado

En estándares anteriores, se permitía la inicialización agregada si el constructor estaba marcado como o , lo que confundía a los usuarios: el objeto se inicializa sin pasar por el constructor. defaultdelete

estructura X { int a = 0 ; x () = predeterminado ; }; X x { 5 }; // C++17: OK // C++20: ningún constructor coincidente para la inicialización de 'X'

Eliminadas las prohibiciones de C++17

Se eliminaron las características raras de la biblioteca estándar prohibidas en C++ 17: [4] [5] [6]

  • allocator<void> - resultó no ser reclamado;
  • algunas de las funciones allocator están duplicadas por la plantilla allocator_traits;
  • raw_storage_iterator - no llama a los constructores y, por lo tanto, tiene una aplicación limitada;
  • get_temporary_buffer - tiene trampas no obvias;
  • is_literal_type - inútil para código genérico;
  • shared_ptr::unique() - debido a la falta de fiabilidad en un entorno de subprocesos múltiples; si realmente lo necesitas, usa ;use_count
  • result_of - reemplazado por invoke_result;
  • uncaught_exception() - reemplazado por uncaught_exceptions.
  • <ccomplex>, <ciso646>, <cstdalign>, <cstdbool>, <ctgmath> — no tienen significado en C++. y otros dejados por compatibilidad con C.<complex.h>

El comentario se eliminó del lenguaje , que se reemplazó en C++11 por . Si necesita compatibilidad con C++ 03, debe escribir algo como throw()noexcept

#si __cplusplus < 201103L #define noexcept throw() #endif

Izquierda:

  • codecvt - de hecho, funcionó muy mal, el comité pidió el uso de bibliotecas especializadas.
  • iterator - es más fácil escribir iteradores desde cero que construir sobre ellos.
  • streams  : no está claro qué hay a cambio.char*
  • creación implícita de la operación "asignar" si hay un constructor de copia y un destructor (y también un constructor de copia si hay una asignación y un destructor); la biblioteca aún se basa en este comportamiento.

Otras prohibiciones de la lengua

  • Interceptación implícita en funciones lambda  , debido a una semántica poco clara. Existe para capturar por puntero y capturar por copia.*this[](){ std::cout << myField; }[this](){ std::cout << myField; }[*this](){ std::cout << myField; }
  • La operación de "coma" en los índices para cualquier a, b y c se debe a un comportamiento no obvio y al deseo de crear una nueva sintaxis para arreglos multidimensionales [7] . Si realmente lo necesitas, por favor escríbenos .a[b,c]a[(b,c)]
  • Conversiones implícitas a un tipo enumerado: para un comportamiento más predecible de la operación de la nueva nave estelar ( , comparación de tres valores).<=>
  • Comparación de dos matrices: para un comportamiento más predecible de la nueva operación "nave estelar" ( , comparación de tres dígitos). Al menos uno debe convertirse en un puntero.<=>

Otras prohibiciones de la biblioteca

  • is_pod - en lugar del concepto complejo de " estructura de datos simple ", es mejor usar propiedades de tipo específicas: se construye de manera trivial, se destruye de manera trivial, etc. Si es muy necesario (por ejemplo, para transferir datos entre complementos ), es equivalente a .is_trivial && is_standard_layout
  • std::rel_ops La nueva operación Starship lo hace mejor.
  • capacidades atómicas  : no está claro cómo trabajar con un puntero, atómicamente o no. Es mejor definirlo con un sistema de tipos, .shared_ptratomic<shared_ptr>
  • string::capacity() - Ahora decidió que no reducirá la capacidad.reserve
  • filesystem::u8path — ahora es diferente de .u8stringstring
  • ATOMIC_FLAG_INIT, atomic_init, ATOMIC_VAR_INIT — ahora lo hace el constructor de plantillas .atomic

Idioma

Cambios menores

  • Se agregó un tipo char8_t sin firmar capaz de contener unidades UTF-8 .
  • using EnumClass, que le permite hacer que el código en lugares clave esté menos desordenado.
  • Inicialización adicional en for by object: [8] . Si el objeto devuelto es temporal , su vida útil se extiende durante todo el ciclo, pero otros objetos temporales se eliminan de forma segura, y si f() es verdadero, la notación es errónea.for (T thing = f(); auto& x : thing.items())items()for (auto& x : f().items())

Módulos

La directiva del compilador #includeen un momento fue un mecanismo C conveniente, que era, de hecho, un ensamblador multiplataforma que "parasitaba" las utilidades del ensamblador: el enlazador y el bibliotecario. De ahí una característica importante de los compiladores de C: fueron los primeros en aparecer en nuevas plataformas después del ensamblador. Pero con la expansión de los proyectos, su tiempo de compilación aumentó cuadráticamente: aumentó tanto la cantidad de unidades de traducción como la cantidad de encabezados conectados a ellas. El mecanismo del módulo ha sido un tema de controversia durante mucho tiempo desde los días de C++11.

Entró en C++20 de la siguiente manera [9] :

// módulo de exportación helloworld.cpp helloworld ; // declaración del módulo import < iostream > ; // declaración de importación export void hola () { // declaración de exportación std :: cout << "¡Hola mundo! \n " ; }

Corrutinas

Una rutina  es una función especial sin pila que puede pausar su ejecución mientras se ejecuta otra función [10] . El estado de la rutina se almacena en la memoria del montón (a menos que el optimizador haya logrado deshacerse de la asignación). Parece una función normal, pero contiene palabras clave de rutina especiales . co_*

tarea <> tcp_echo_server () { datos de caracteres [ 1024 ]; para (;;) { size_t n = co_await socket . async_read_some ( búfer ( datos )); co_await async_write ( socket , buffer ( datos , n )); } }

Físicamente, una rutina es una función que devuelve un objeto de promesa recién creado. Cada vez que el usuario hace algo con el objeto de promesa, el control se transfiere al código de rutina. Varias promesas estándar están disponibles en la biblioteca; por ejemplo, proporciona una evaluación diferida . lazy<T>

typename se declara redundante donde solo se permite el tipo

En algunos lugares de las plantillas, la palabra typename(que explica que  es un tipo y no una función) ya no es necesaria [11] . Estos lugares incluyen… Object::Thing

  • escriba después de  -newauto x = new Object::Thing;
  • escribe  -usingusing Thing = Object::Thing;
  • tipo de retorno final ;auto f() -> Object::Thing
  • tipo predeterminado en la plantillatemplate<class T = Object::Thing> T f();
  • escriba static_cast , const_cast , reinterpret_cast , dynamic_cast  —auto x = static_cast<Object::Thing>(y);
  • tipo de variable/función en el espacio de nombres (incluido el global) o clase:Object::Thing variable;
  • tipo de parámetro de función/plantilla, si hay un identificador (excepto las expresiones relacionadas con el cálculo del valor del parámetro predeterminado) —void func(Object::Thing x);
plantilla < clase T > T :: Rf ( ); // OK ahora, escriba la plantilla de espacio de nombres global < class T > void f ( T :: R ); // Necesita el nombre de tipo, sin él es un intento de crear una variable nula inicializada con T::R template < class T > struct S { usando Ptr = PtrTraits < T >:: Ptr ; // Ahora bien, escriba usando T :: R f ( T :: P p ) { // Ahora bien, escriba class return static_cast < T :: R > ( p ); // Ahora bien, static_cast } g automático () -> S < T *>:: Ptr ; // OK ahora, tipo de retorno final }; plantilla < nombre de tipo T > void f () { vacío ( * pf )( T :: X ); // Permanece OK, variable de tipo void* inicializada con T::X void g ( T :: X ); // Necesita typename, sin él, es un intento de crear una variable vacía inicializada con T::X }

Cálculo del tamaño de una matriz en new

El tamaño de la matriz en el nuevo operador ahora se deduce automáticamente [12]

doble a []{ 1 , 2 , 3 }; // Sigue OK double * p = new double []{ 1 , 2 , 3 }; // Ahora ok

Nuevos atributos

  • [[no_unique_address]] - una variable sin datos puede no ocupar espacio, y otras variables pueden almacenarse en los "agujeros" de una variable con datos. Pero: las variables del mismo tipo nunca pueden estar en la misma dirección.
plantilla < Asignador de clase > Almacenamiento de clase { privado : [[ no_unique_address ]] Asignador alloc ; };
  • [[nodiscard("причина")]] es una extensión del atributo C++17 del mismo nombre. Indica que el valor de retorno de una función no debe ignorarse y muestra el motivo.
class XmlReader { // Lector de tipo de flujo XML public : [[ nodiscard ( "Comprobar resultado o usar requireTag" )]] bool getTag ( const char * nombre ); void requireTag ( const char * nombre ) { if ( ! getTag ( nombre )) throw std :: logic_error ( std :: cadena ( "requireTag: " ) + nombre + " not found" ); } };
  • [[likely]] / [[unlikely]] - anotar bajo qué ramas es necesario optimizar el programa para el mejor trabajo del predictor de ramas . Esta técnica ya está implementada en algunos compiladores, consulte __builtin_expectGCC, por ejemplo.
si ( x > y ) [[ improbable ]] { std :: cout << "Rara vez sucede" << std :: endl ; } más [[ probable ]] { std :: cout << "A menudo sucede" << std :: endl ; }

Constexpr extendido

Constexpr permite:

  • llamar a funciones virtuales [13] ;
  • llamar a los destructores, que también deben ser ;constexpr
  • trabajar con union[14] ;
  • trabajar con  - el bloque de intercepción no hace nada, y lanzar una excepción en este contexto, como antes, calculará la función durante la ejecución [15] ;try
  • uso y [16] ;dynamic_casttypeid
  • new, con algunas restricciones [17] ;
  • asmsi no se llama en la compilación;
  • variables no inicializadas.

En teoría, tal construcción permitirá, por ejemplo, hacer que un std::vector constante simplemente apunte a la memoria del std::initializer_list correspondiente , y una memoria dinámica de asignación ordinaria no constante.

Llamadas extendidas a la función lambda en tiempo de compilación; por ejemplo, puede ordenar std::tuple .

Palabras clave consteval y constinit

No es necesario llamar al código constexpr en la compilación, y basta con escribirlo para que la cadena constexpr se rompa en el constructor std::set y la inicialización se produzca en la ejecución. A veces, esto no es deseable: si la variable se usa durante la inicialización del programa (un inconveniente bien conocido de C ++: un orden de inicialización no controlado de los archivos CPP), grande (por ejemplo, una tabla grande) o difícil de calcular (inicialización de la misma tabla, que toma O (n²)). Y los programadores simplemente tienen un interés deportivo en transferir el código a la compilación. Para dar confianza, se utilizan dos nuevas palabras clave: std::set<std::string_view> dic { "alpha", "bravo" };

  • constevalen funciones: requiere que la función se ejecute cuando se compila. No se permite una llamada desde un contexto que no sea ejecutable en tiempo de compilación. Reemplazado en encabezados de compatibilidad con compiladores más antiguos con .constexpr
  • constiniten una variable: requiere que la variable sea evaluada en tiempo de compilación. Reemplazado con una cadena vacía en los encabezados de compatibilidad con compiladores más antiguos.
consteval int sqr ( int n ) { devolver n * n ; } const auto res2 = sqr ( 5 ) ; int principal () { intn ; _ estándar :: cin >> n ; std :: cout << sqr ( n ) << std :: endl ; // error, no computable al compilar }

explícito (bool)

La palabra clave se puede escribir junto con una expresión constante booleana: si es verdadera, la conversión solo es posible explícitamente. Simplifica la metaprogramación, reemplaza el modismo SFINAE [18] . explicit

// Was, std::forward omitido por brevedad template < class T > struct Wrapper { template < class U , std :: enable_if_t < std :: is_convertible_v < U , T >>* = nullptr > Envoltorio ( U const & u ) : t_ ( u ) {} plantilla < clase U , std :: enable_if_t <! std :: is_convertible_v < U , T >>* = nullptr > Envoltorio explícito ( U const & u ) : t_ ( u ) {} T t_ ; }; // Se convirtió en template < class T > struct Wrapper { template < class U > explicit ( ! std :: is_convertible_v < U , T > ) Wrapper ( U const & u ) : t_ ( u ) {} T t_ ; };

Comparación de tres dígitos ("nave estelar")

La operación le permite comparar objetos usando uno de tres métodos: <=>

  • Orden parcial : menor que, equivalente, mayor que, incomparable.
  • Orden débil : menor que, equivalente, mayor que. Puede suceder que el valor de algún campo o función pública sea diferente para objetos equivalentes. El concepto de "equivalente" es transitivo.
  • Orden fuerte (lineal) (menor que, igual, mayor que). Los objetos iguales solo se distinguen por la dirección.
clase PersonInFamilyTree { // ... público : std :: operador de orden_parcial <=> ( const PersonInFamilyTree & that ) const { if ( esto -> es_la_misma_persona_que ( esa )) return orden_parcial :: equivalente ; if ( esto -> es_hijo_transitivo_de ( eso )) devuelve orden_parcial :: menos ; if ( eso . es_hijo_transitivo_de ( * esto )) devuelve orden_parcial :: mayor ; volver orden_parcial :: desordenado ; } };

El nombre "nave estelar" proviene de un antiguo juego de Star Trek : estos tres personajes significaban " Enterprise ".

La versión del cuerpo de la operación Starship simplemente compara todos los campos en orden de declaración. La operación "es igual" al cuerpo también es posible , también compara todos los campos en el orden de declaración y automáticamente declara la operación "no es igual" [19] . =default=default

Conceptos

Concepto: los requisitos para los parámetros de la plantilla para que esta plantilla tenga sentido. Durante la mayor parte de la vida de C++, el concepto se ha descrito verbalmente, con errores complejos en encabezados válidos como STL si el programador no encajaba en el concepto. Si el programador escribe la plantilla él mismo, puede dejar accidentalmente el concepto y no verlo en el programa de prueba, porque los tipos más simples parecen tener muchas funciones predeterminadas como el constructor de copias, la asignación y las operaciones aritméticas. int

plantilla < claseT > _ concepto bool EqualityComparable () { return requiere ( T a , T b ) { { a == b } -> Booleano ; // Un concepto que significa un tipo para convertir a booleano { a != b } -> Boolean ; }; }

Constantes de cadena como parámetros de plantilla

La compilación del procesamiento de cadenas ha sido un sueño de C++ durante mucho tiempo, y el próximo paso hacia él son las constantes de cadenas en las plantillas [20] . En particular, me gustaría convertir expresiones regulares a bytecode ya en la compilación. Las bibliotecas de expresiones regulares experimentales ya han visto aceleraciones de hasta 3000 veces en comparación con std::regex .

plantilla < auto & str > vacío f () { // cadena = const char (&)[7] } f < "foobar" > ();

Inicialización de estructura con nombre

La inicialización ordinal de estructuras C es errónea si se espera la expansión de la estructura o si se pueden confundir dos elementos vecinos. Se agregó el nuevo estándar , que existió en C durante mucho tiempo, pero no se formalizó en C++ [21] . Point p { 10, 20 };Point p { .x=10, .y=20 };

Además, esta construcción le permite inicializar exactamente la opción unionque necesita.

unión FlotanteInt { flotar comoFlotar ; int32_t comoInt ; }; Entero flotante x { . comoInt = 42 };

Eliminado en comparación con C:

  • Inicialización de matriz con nombre : a partir de C++ 11, los corchetes al comienzo de una expresión indican una función lambda.int arr[3] = {[1] = 5};
  • declaración fuera de servicio  : conflictos con los autodestructores de C ++: ¿construido en un orden, destruido en otro?Point p { .y=20, .x=10 };
  • inicialización con nombre de miembros de estructuras anidadas  - rara vez se usastruct B b = {.a.x = 0};
  • mezcla de inicialización con nombre y ordinal:Point p {.x = 1, 2};

Cambios en las funciones lambda

Las funciones Lambda aparecieron en C++ 11 después de otros lenguajes de programación. Resuelven varios problemas a la vez: reemplazan el preprocesador si es necesario ejecutar el mismo código en dos lugares de la función, y lleva mucho tiempo ponerlo en un objeto/función separado; mueva el texto de la función más cerca de donde se requiere; le permiten escribir en un estilo funcional. Llamado así por el cálculo lambda , uno de los fundamentos de la programación funcional.

Intercepción explícita de un objeto en una función lambda [=, this](){}y [=, *this](){}[22] . Como se mencionó anteriormente, se prohibió la intercepción implícita en las funciones lambda. this

Sintaxis de plantilla lambda tradicional en lugar de C++14 . Esta sintaxis es más conveniente si necesita realizar una autocomprobación o calcular algún tipo derivado [23] . [](auto x)

// Fue automático f = []( vector automático ) { usando T = typename decltype ( vector ) :: value_type ; ... }; // Se convirtió en automático f = [] < nombre de tipo T > ( std :: vector < T > vector ) { ... };

Funciones lambda en contextos no computables : firmas, tipos de devolución, parámetros de plantilla [24] [25] .

std :: prioridad_cola < int , // tipo de elemento std :: vector < int > , // tipo de contenedor decltype ( []( int a , int b ) -> bool { // tipo de función de comparación de elementos return a > b ; }) > q ;

Para que este código funcione, se necesita un cambio más: la función lambda sin ganchos ahora tiene un constructor predeterminado y un operador de asignación [24] [26] . Todas las instancias de esta pseudoclase hacen lo mismo, y no hay forma de forzar una cola de prioridad dada para comparar en un orden diferente. Los constructores de copiar y mover estaban originalmente en todas las funciones lambda.

En la lista de intercepciones de la función lambda, ahora es posible mantener la operación de expandir la parte variable [24] [27]  - antes, para esto era necesario incluir un objeto tupla. Por ejemplo, esta plantilla devuelve una función lambda que se puede llamar en cualquier momento si se desea: llama a la función foo () y ya contiene copias de todos los datos necesarios para llamar.

// Fue plantilla < clase ... Args > auto delay_invoke_foo ( Argumentos ... argumentos ) { return [ tup = std :: make_tuple ( std :: move ( args )...)]() -> decltype ( auto ) { return std :: apply ([]( auto const & ... args ) -> decltype ( auto ) { return foo ( argumentos ...); }, sup ); }; } // Se convirtió en plantilla < clase ... Args > auto delay_invoke_foo ( Argumentos ... argumentos ) { return [ argumentos = std :: mover ( argumentos )...]() -> decltype ( auto ) { return foo ( argumentos ...); }; }

Cambios editoriales

Nuevas condiciones de movimiento implícitas

Condiciones aclaradas cuando se requiere mover implícitamente un objeto, especialmente cuando se lanzan excepciones: [28]

vacío f () { Tx ; _ prueba { T y ; prueba { g ( x );} atrapar (...) { si ( /*...*/ ) tirar x ; // no se moverá - x fuera del bloque try throw y ; // mover - y dentro del bloque de prueba } g ( y ); } atrapar (...) { g ( x ); // g(y); // error } }

Números con signo - complemento a dos

Cuando el lenguaje C estaba en su infancia, había un "zoológico" de diferentes máquinas, y la máquina educativa MIX , inventada por Donald Knuth , reflejaba esto: un byte podía almacenar de 64 a 100 valores diferentes, y el formato de los números con signo no se especificó. Durante más de cuarenta años, se decidieron por el byte de 8 bits y el complemento a dos , principalmente por su simplicidad e interoperabilidad , y esto se señaló en el estándar [29] .

El desbordamiento aritmético en la aritmética sin signo es equivalente a las operaciones de módulo , en la aritmética con signo: comportamiento indefinido .

Nuevo modelo de memoria

Obsoleto oralmente con C++17 , destinado a PowerPC y ARM, formalizado y vuelto a usar. Reforzado [30] . memory_order_consumememory_order_seq_cst

Biblioteca

Cambios menores

  • Nuevas versiones relacionadas con arreglos [31] [32] .make_unique/make_shared
  • atomic<shared_ptr<>>y .atomic<weak_ptr<>>
  • atomic_ref<>, un objeto que te permite hacer cualquier cosa atómica [33] .
  • std::erase, , simplificar la metaprogramación [34] .std::erase_if
  • map.contains[35] .
  • El nuevo encabezado  es un lugar estándar para anuncios relacionados con el desarrollo de una biblioteca estándar particular [36] . Las declaraciones están definidas por la implementación.<version>
  • to_address — conversión de un objeto similar a un puntero en un puntero [37] . ya existe, pero requiere desreferencia, lo que puede convertirse en un comportamiento indefinido .addressof
  • Nuevo #definepara probar la funcionalidad del compilador y la biblioteca [38] . Los estándares de C++ son enormes y no todos los desarrolladores de compiladores los incorporan rápidamente a sus productos. Y algunos, la recolección de basura de C ++ 11 , siguen siendo stubs hasta el día de hoy (2021), no implementados en ningún compilador.
  • Curry simplificado a través de [39] .bind_front
  • source_location - un contenedor para macros y similares en C++.__FILE__
  • Nuevo título con constantes matemáticas [40] . Antes de eso, incluso los habituales π y e solo existían como extensiones.<numbers>

Declaración de función constexpr

  • std::pointer_traits[41] .
  • xxx.empty()y algunos otros Escribir en cambio se ha convertido en un error estándar de C++ [42] [43] , y se declara .xxx.empty();xxx.clear();[[nodiscard]]
  • <numeric>[44] .
  • constructores-destructores de std::vector y std::string , una consecuencia de las relajaciones constexpr. En el momento de la revisión (mayo de 2020), ningún compilador admite esto [45] .

Biblioteca de formato

printf es demasiado bajo, peligroso y no extensible. Las características estándar de C++ solo permiten la concatenación de cadenas y, por lo tanto, son inconvenientes para la localización .

Por lo tanto, C++20 introdujo un mecanismo de formateo de cadenas más seguro para tipos basado en Python [46] .

carácter c = 120 ; auto s1 = estándar :: formato ( "{:+06d}" , c ); // "+00120" auto s2 = estándar :: formato ( "{:#06x}" , 0xa ); // "0x000a" auto s3 = std :: format ( "{:<06}" , -42 ); // "-42 " (0 se ignora debido a la alineación <)

Capacidades:

  • El mismo parámetro se puede formatear cualquier número de veces de diferentes maneras.
  • Las sustituciones se pueden intercambiar.
  • Alineación izquierda, centro y derecha, cualquier carácter.
  • De forma predeterminada, los números, las fechas, etc. tienen un formato neutral para la configuración regional; si se necesita localización, se establece explícitamente.
  • Funciona a través de plantillas y, por lo tanto, se extiende a cualquier tipo.
  • Los paréntesis se pueden escapar {{ }} .

Punteros no propietarios a una matriz (intervalo)

std::string_view resultó ser un gran objeto, e hicieron lo mismo con las matrices - std::span [47] . Al mismo tiempo, span puede cambiar el contenido de la memoria, a diferencia de string_view .

void hacer_algo ( std :: span < int > p ) { std2 :: ordenar ( p ); para ( int & v : p ) { v += pag [ 0 ]; } } // ... estándar :: vector < int > v ; hacer_algo ( v ); datosinternos [ 1024 ] ; hacer_algo ( datos ); impulsar :: contenedor :: vector_pequeño < int , 32 > sm ; hacer_algo ( sm );

Biblioteca para trabajar con bits <bit>

Biblioteca para trabajar con "flujos de salida" sincronizados <syncstream>

El subproceso de salida , por regla general, maneja el acceso desde diferentes subprocesos de ejecución por su cuenta . En el registro de subprocesos múltiples , surge la tarea: recopilar datos (por ejemplo, una línea de texto) en un búfer de longitud suficiente y enviarlos a la secuencia en una sola operación.

Para ello se utiliza una clase simple, que es descendiente de . ostream

osyncstream { cout } << "La respuesta es" << 6 * 7 << endl ;

Toda la salida al subproceso esclavo ocurre en una sola operación en el destructor.

Biblioteca de rangos <rangos>

Se utiliza una biblioteca compleja donde se necesita un acceso uniforme, como std::vector y std::deque [48] .

Biblioteca de calendarios y zonas horarias en <crono>

Biblioteca compleja para cálculos de calendario [49] .

auto d1 = 2018_y / mar / 27 ; _ auto d2 = 27_d / mar / 2018 ; _ auto d3 = 27 mar / 2018 ; _ año_mes_día hoy = piso < días > ( system_clock :: ahora ()); afirmar ( d1 == d2 ); afirmar ( d2 == d3 ); afirmar ( d3 == hoy );

La letra j significa unir  , es decir, cuando se destruye el objeto de subproceso, el sistema espera a que se complete la tarea.

Además, usando la biblioteca , puede pedirle al hilo que se detenga. stop_token

#incluir <subproceso> #incluir <iostream> utilizando el espacio de nombres std :: literales :: chrono_literals ; void f ( std :: stop_token stop_token , valor int ) { while ( ! stop_token . stop_requested ()) { std :: cout << valor ++ << ' ' << std :: flush ; std :: this_thread :: sleep_for ( 200ms ) ; } std :: cout << std :: endl ; } int principal () { std :: hilo jthread ( f , 5 ); // imprime 5 6 7 8... durante aproximadamente 3 segundos std :: this_thread :: sleep_for ( 3 s ); // El destructor de jthread llama a request_stop() y join(). }

Barreras y cerrojos

Una barrera es un mecanismo de sincronización entre subprocesos que funciona así: tan pronto como se reúnen n subprocesos en la barrera , ejecuta el objeto de función y los libera. Por lo general, se utiliza para la coordinación periódica de tareas parcialmente paralelizadas: después de que los subprocesos hayan completado cada uno su parte, el coordinador dispara y decide qué hacer a continuación.

Un pestillo es una barrera de una sola vez simplificada [50] .

Búsqueda heterogénea en unordered_set / map

Propósito principal: las claves de almacenamiento son objetos "pesados" (por ejemplo, string ), pero los livianos también son aceptables como clave de búsqueda: string_view e incluso const char*. Se implementa de manera muy simple: se agrega una función de plantilla find que acepta cualquier tipo, mientras que la búsqueda heterogénea en sí misma se incluye en el tipo de marcador [51] . Se admiten cuatro funciones: buscar, contar, rango_igual, contiene. C++23 espera más funciones que admitan búsquedas heterogéneas, como erase [52] . is_transparent

Para árboles de búsqueda autoequilibrados ( set / map ) implementados en C++14.

Esta función no está habilitada de forma predeterminada debido a un error: es posible que la conversión de tipos no conserve las relaciones en las que trabaja el contenedor. Por ejemplo , pero . Por lo tanto, la búsqueda de un número fraccionario en no conducirá a lo que necesita [53] . Por lo que el propio programador debe permitir aquellas claves alternativas que sean ciertamente adecuadas. 1.0 < 1.1static_cast<int>(1.0) == static_cast<int>(1.1)set<int>

estructura string_hash { usando is_transparent = void ; [[ nodiscard ]] operador size_t ()( const char * txt ) const { return std :: hash < std :: string_view > {}( txt ); } [[ nodiscard ]] operador size_t ()( std :: string_view txt ) const { return std :: hash < std :: string_view > {}( txt ); } [[ nodiscard ]] operador size_t ()( const std :: string & txt ) const { devuelve estándar :: hash < estándar :: cadena > {}( txt ); } }; std :: unordered_map < std :: string , int , string_hash , std :: equal_to <>> m { { "Hello Super Long String" , 1 }, { "Otra cadena larga" , 2 }, { "Esto no puede caer en Búfer SSO" , 3 } }; booleano encontrado = m . contiene ( "Hola, cadena súper larga" ); std :: cout << "Encontrado: " << std :: boolalpha << encontrado << '\n' ;

Implementadas como bibliotecas experimentales

  • Concurrency v2 [54] , incluidos los bloques de tareas. La versión 1 está incluida en C++17.
  • Reflexión v1 [55]
  • Red v1 [56]

Dejado para el futuro

  • Contratos - hay una oferta competidora
  • Metaclases
  • Intérpretes
  • Propiedades
  • Futuro extendido

Véase también

Notas

  1. ISO/IEC 14882:2020  (inglés) . ISO . Recuperado: 21 de diciembre de 2020.
  2. ↑ Estado actual : C++ estándar  . Consultado el 8 de febrero de 2019. Archivado desde el original el 8 de septiembre de 2020.
  3. P1152R4: Obsoletovolatile . Consultado el 9 de agosto de 2022. Archivado desde el original el 9 de agosto de 2022.
  4. Obsolescencia de las piezas de la biblioteca vestigial en C++17 . Consultado el 29 de enero de 2021. Archivado desde el original el 13 de septiembre de 2017.
  5. Obsoleto <codecvt> . Consultado el 29 de enero de 2021. Archivado desde el original el 16 de septiembre de 2017.
  6. Resolución propuesta para CA 14 (shared_ptr use_count/unique) . Consultado el 29 de enero de 2021. Archivado desde el original el 7 de julio de 2017.
  7. P1161R3: Usos obsoletos del operador de coma en  expresiones de subíndice . www.open-std.org . Consultado el 21 de diciembre de 2020. Archivado desde el original el 9 de noviembre de 2020.
  8. Informe de viaje: reunión de estándares ISO C++ de otoño (Albuquerque) – Sutter's Mill . Consultado el 8 de febrero de 2019. Archivado desde el original el 13 de febrero de 2019.
  9. Módulos (desde C++20) - cppreference.com . Consultado el 2 de febrero de 2021. Archivado desde el original el 27 de enero de 2021.
  10. Corrutinas (C++20) - cppreference.com . Consultado el 3 de febrero de 2021. Archivado desde el original el 25 de marzo de 2021.
  11. ¡Abajo con typename! . Consultado el 13 de agosto de 2020. Archivado desde el original el 22 de abril de 2018.
  12. Copia archivada . Consultado el 14 de agosto de 2020. Archivado desde el original el 15 de agosto de 2020.
  13. Permitir llamadas a funciones virtuales en expresiones constantes . www.open-std.org . Consultado el 11 de marzo de 2019. Archivado desde el original el 11 de junio de 2018.
  14. P1330R0 - Cambiar el miembro activo de un sindicato dentro de constexpr . Consultado el 13 de agosto de 2020. Archivado desde el original el 26 de julio de 2019.
  15. P1002R0 - Bloques Try-catch en funciones constexpr . Consultado el 8 de febrero de 2019. Archivado desde el original el 11 de noviembre de 2018.
  16. P1327R0 - Permitir dynamic_cast, typeid polimórfico en Constant Expressions . Consultado el 13 de agosto de 2020. Archivado desde el original el 26 de julio de 2019.
  17. ↑ Más contenedores constexpr  . www.open-std.org . Consultado el 21 de diciembre de 2020. Archivado desde el original el 14 de noviembre de 2020.
  18. Constructores condicionalmente explícitos de C++20 | Blog del equipo de C++ . Consultado el 2 de febrero de 2021. Archivado desde el original el 23 de enero de 2021.
  19. Comparaciones predeterminadas (desde C++20) - cppreference.com . Consultado el 7 de enero de 2022. Archivado desde el original el 7 de enero de 2022.
  20. Literales de cadena como parámetros de plantilla que no son de tipo . Archivado desde el original el 11 de diciembre de 2017.
  21. Tim Shen, Richard Smith. P0329R4:  Redacción de inicialización designada . http://www.open-std.org/ . Consultado el 21 de diciembre de 2020. Archivado desde el original el 15 de noviembre de 2020.
  22. Thomas Köppe. Permitir la captura de lambda [=, esto ] . Consultado el 8 de febrero de 2019. Archivado desde el original el 9 de febrero de 2019.
  23. Sintaxis de plantilla familiar para  lambdas genéricas . Consultado el 8 de febrero de 2019. Archivado desde el original el 21 de noviembre de 2018.
  24. ↑ 1 2 3 Informe de viaje: Reunión de estándares de C++ en Albuquerque, noviembre de 2017  , ¡Ahí está Waldo!  (20 de noviembre de 2017). Archivado desde el original el 11 de diciembre de 2017. Consultado el 8 de febrero de 2019.
  25. Redacción de lambdas en contextos no evaluados . Archivado desde el original el 12 de diciembre de 2017.
  26. Lambdas sin estado construibles y asignables por defecto . Archivado desde el original el 12 de diciembre de 2017.
  27. Paquete de expansión en lambda init-capture . www.open-std.org . Consultado el 11 de diciembre de 2017. Archivado desde el original el 14 de febrero de 2020.
  28. Copia archivada . Consultado el 14 de agosto de 2020. Archivado desde el original el 12 de agosto de 2020.
  29. P1236R0: Redacción alternativa para P0907R4 Los enteros con signo son complemento a dos . Archivado desde el original el 11 de noviembre de 2018.
  30. P0668R4: Revisión del modelo de memoria de C++ . Archivado desde el original el 11 de noviembre de 2018.
  31. std::make_unique, std::make_unique_for_overwrite - cppreference.com . Consultado el 29 de enero de 2021. Archivado desde el original el 3 de febrero de 2021.
  32. std::make_shared, std::make_shared_for_overwrite - cppreference.com . Consultado el 29 de enero de 2021. Archivado desde el original el 3 de febrero de 2021.
  33. std::atomic_ref-cppreference.com . Consultado el 2 de marzo de 2021. Archivado desde el original el 27 de abril de 2021.
  34. Adopte el borrado consistente de contenedores de Library Fundamentals 2 para C++20 . Consultado el 2 de febrero de 2021. Archivado desde el original el 8 de marzo de 2021.
  35. std::map<Key,T,Compare,Allocator>::contains - cppreference.com . Consultado el 2 de febrero de 2021. Archivado desde el original el 11 de junio de 2018.
  36. Copia archivada . Consultado el 2 de febrero de 2021. Archivado desde el original el 20 de enero de 2021.
  37. Utilidad para convertir un puntero en un puntero sin procesar . Consultado el 2 de febrero de 2021. Archivado desde el original el 20 de febrero de 2018.
  38. Integración de macros de prueba de características en C++ WD . Consultado el 8 de febrero de 2019. Archivado desde el original el 20 de julio de 2018.
  39. Aplicación de función parcial simplificada . Consultado el 2 de febrero de 2021. Archivado desde el original el 28 de septiembre de 2020.
  40. Encabezado de biblioteca estándar <numbers> - cppreference.com . Consultado el 2 de marzo de 2021. Archivado desde el original el 25 de enero de 2021.
  41. P1006R1 - Constexpr en std::pointer_traits . Consultado el 8 de febrero de 2019. Archivado desde el original el 11 de noviembre de 2018.
  42. string::empty - Referencia de C++ . Consultado el 29 de enero de 2021. Archivado desde el original el 28 de octubre de 2020.
  43. 100 errores en proyectos C/C de código abierto . Consultado el 29 de enero de 2021. Archivado desde el original el 26 de enero de 2021.
  44. Biblioteca numérica - cppreference.com . Consultado el 2 de febrero de 2021. Archivado desde el original el 21 de abril de 2021.
  45. C++20: Las funciones no habladas - Revista legible por humanos . Consultado el 8 de diciembre de 2020. Archivado desde el original el 30 de noviembre de 2020.
  46. Biblioteca de formato (C++20) - cppreference.com . Consultado el 29 de enero de 2021. Archivado desde el original el 31 de enero de 2021.
  47. ↑ Encabezado de biblioteca estándar  - cppreference.com . Consultado el 29 de enero de 2021. Archivado desde el original el 27 de abril de 2021.
  48. Biblioteca de rangos (C++20) - cppreference.com . Consultado el 3 de febrero de 2021. Archivado desde el original el 16 de enero de 2021.
  49. Ampliación de <crono> a calendarios y zonas horarias . Consultado el 3 de febrero de 2021. Archivado desde el original el 13 de mayo de 2018.
  50. P0342R0: Barreras de tiempo . Consultado el 8 de febrero de 2019. Archivado desde el original el 24 de noviembre de 2019.
  51. std::unordered_set<Key,Hash,KeyEqual,Allocator>::find - cppreference.com . Consultado el 31 de mayo de 2022. Archivado desde el original el 31 de mayo de 2022.
  52. C++20: Búsqueda heterogénea en contenedores (no)ordenados - Historias de C++ . Consultado el 17 de mayo de 2022. Archivado desde el original el 24 de mayo de 2022.
  53. rappel / Sugerencia de la semana n.º 144: Búsqueda heterogénea en contenedores asociativos . Consultado el 17 de mayo de 2022. Archivado desde el original el 18 de mayo de 2022.
  54. Extensiones de C++ para Parallelism Versión 2 .
  55. Extensiones de C++ para Reflection .
  56. Extensiones de C++ para redes .