En diciembre de 2020 se publicó oficialmente C++20, una de las revisiones más ambiciosas del estándar del lenguaje desde C++11. Para muchos expertos, no es “una versión más”, sino el punto en el que C++ se adapta de verdad a la programación moderna: genéricos más seguros, módulos, corutinas, nuevas utilidades de biblioteca y una limpieza profunda de la herencia histórica del lenguaje.
Cuatro años después, con el estándar ya consolidado y soporte estable en los principales compiladores, merece la pena repasar qué aporta realmente C++20 y por qué está cambiando la manera en que se escriben aplicaciones de alto rendimiento.
Un estándar con más cambios que C++14 y C++17 juntos
C++20 reemplazó a C++17 y, a su vez, ha sido la base sobre la que se ha construido C++23. El comité de estandarización (WG21) lo dio por finalizado en febrero de 2020 y fue aprobado en septiembre de ese mismo año.
La lista de novedades es muy larga: el estándar incorpora grandes bloques de funcionalidad (conceptos, módulos, corutinas, rangos), amplía el uso de constexpr, introduce nuevos keywords como consteval o constinit, define de forma explícita que los enteros con signo usan complemento a dos, revisa el modelo de memoria y añade una cantidad notable de utilidades a la biblioteca estándar.
C++20 es, en la práctica, el “nuevo mínimo” que muchos equipos empiezan a exigir para proyectos modernos.
Conceptos: plantillas más legibles y con errores comprensibles
Las plantillas han sido siempre una de las mayores fortalezas —y dolores de cabeza— de C++. Hasta ahora, los errores de compilación por usar mal una plantilla podían ocupar decenas de líneas.
Los conceptos (concepts) permiten expresar, dentro del propio lenguaje, qué requisitos debe cumplir un tipo para usarse en una plantilla: por ejemplo, que tenga cierto operador, cierto alias de tipo o cierta función disponible.
En lugar de comentar precondiciones o confiar en la documentación, se escribe:
template <Sortable T>
void ordenar(std::span<T> datos);
Lenguaje del código: HTML, XML (xml)
donde Sortable es un concepto que describe qué sabe hacer ese tipo.
El resultado:
- Mensajes de error más claros.
- APIs más autoexplicativas.
- Posibilidad de sobrecargar en función de capacidades reales de los tipos, no solo por su jerarquía de herencia.
Módulos: adiós al infierno de los headers (al menos, en teoría)
Otra de las grandes novedades son los módulos. Hasta C++20, el modelo de compilación seguía anclado en los ficheros de cabecera (.h) y las directivas #include, con problemas conocidos: recompilaciones enormes por pequeños cambios, ambigüedades de macros, tiempos de compilación altos…
Los módulos introducen una forma nativa de declarar qué exporta una unidad de traducción y qué importa de otras, sin depender de includes textuales. Eso permite:
- Mejorar de forma significativa los tiempos de compilación.
- Reducir errores por macros y redefiniciones.
- Encapsular mejor los detalles internos de una librería.
Su adopción está siendo gradual, porque requiere soporte completo de compiladores y tooling, pero marcan el camino hacia un C++ más manejable en proyectos grandes.
Corutinas: asincronía sin pelearse con threads
Las corutinas son otra pieza clave de C++20. Permiten escribir código asíncrono o cooperativo con una sintaxis casi idéntica a la del código secuencial, usando las nuevas palabras clave co_await, co_return y co_yield.
En la práctica, esto facilita implementar:
- servidores de red que manejan miles de conexiones,
- pipelines de procesamiento de datos,
- generadores de secuencias perezosas,
sin recurrir a máquinas de estados manuales o a una proliferación incontrolable de hilos. La complejidad está en las bibliotecas que definen tipos “esperables” (awaitable), pero el desarrollador de aplicación gana expresividad y claridad.
El operador “nave espacial” y otras mejoras del núcleo
C++20 también introduce cambios más “terrenales”, pero muy útiles en el día a día:
- Operador
<=>(“spaceship”): permite definir de una sola vez la comparación de un tipo, obteniendo automáticamente<,<=,>,>=y, en muchos casos, también la igualdad. constevale immediate functions: funciones que deben evaluarse en tiempo de compilación, garantizando que ciertos cálculos y validaciones ocurran antes de ejecutar el programa.constinit: asegura que una variable con duración de almacenamiento estático se inicializa de forma constante en tiempo de compilación, evitando sutiles problemas de orden de inicialización global.- Más
constexpr: ahora se permitenvirtual,try/catch,dynamic_cast,typeidy otras construcciones dentro de expresiones constantes, lo que acerca C++ a un lenguaje capaz de hacer metaprogramación muy potente en tiempo de compilación.
Además, el estándar fija por fin que los enteros con signo usan representación en complemento a dos, alineándose con la práctica real de la industria y simplificando ciertas optimizaciones y razonamientos.
Biblioteca estándar: rangos, span, format, chrono y mucho más
La parte de biblioteca (STL) recibe un auténtico aluvión de mejoras:
- Rangos (
<ranges>): unifican el trabajo con secuencias y algoritmos mediante vistas perezosas, composición funcional y mejor interoperabilidad con contenedores estándar. std::span: una vista ligera sobre un bloque contiguo de memoria (array,std::vector, etc.), similar astd::string_viewpero mutable y para cualquier tipo.std::formaty nuevas capacidades destd::chrono: facilitan formatear texto y trabajar con fechas, calendarios y zonas horarias de manera más moderna.- Nuevas utilidades de concurrencia y sincronización: como
std::jthread,std::stop_token,std::atomic_ref, operaciones atómicas de espera/notificación, semáforos, latches y barriers. - Operaciones de bits (
std::bit_…): conteos de ceros/unos líderes o finales, logaritmos base 2, etcétera. std::span,std::source_location,std::bit_cast, contenedoresconstexprcomostd::stringystd::vector, y muchas otras piezas que modernizan la biblioteca.
Todo ello hace que se pueda escribir código más seguro y expresivo usando componentes estándar, reduciendo la necesidad de recurrir a bibliotecas externas para casos comunes.
Limpieza del lenguaje: menos equipaje heredado
C++20 también aprovecha para podar elementos antiguos o poco seguros:
- Se eliminan cabeceras de estilo C que no aportaban nada en C++ (
<ccomplex>,<cstdbool>, etc.). - Se retiran características obsoletas como las cláusulas
throwen las declaraciones de funciones. - Se depreca el uso de
volatileen la mayoría de contextos, clarificando que no es la herramienta adecuada para concurrencia. - Se incentiva el uso de nuevos atributos como
[[likely]],[[unlikely]]o[[nodiscard]]para ayudar al compilador y documentar mejor la intención del código.
No es una ruptura con el pasado, pero sí un paso firme hacia un C++ más coherente.
Soporte en compiladores y adopción
Aunque el estándar se publicó en 2020, el soporte completo ha llegado de forma gradual. Visual Studio 2019, GCC y Clang han ido incorporando la mayoría de características bajo las opciones -std=c++20 o equivalentes, hasta el punto de que hoy, en la práctica, C++20 es utilizable en entornos Windows, Linux, Android o iOS con los compiladores modernos habituales.
Para muchos equipos, el reto ya no es tanto “¿está soportado?” como decidir cuándo migrar proyectos grandes y cómo combinar nuevo código moderno con bases de código heredadas.
Qué significa C++20 para los desarrolladores
En conjunto, C++20 consolida una tendencia clara:
- Más expresividad (conceptos, rangos, corutinas).
- Más seguridad en tiempo de compilación (consteval, constinit,
constexprampliado). - Mejor rendimiento y control fino, manteniendo la filosofía original del lenguaje.
El precio es una mayor complejidad conceptual: aprender “todo C++20” lleva tiempo, y la convivencia con código antiguo puede generar fricción. Pero el estándar ofrece ya un conjunto sólido de herramientas para escribir software moderno sin renunciar al rendimiento cercano al metal que siempre ha caracterizado a C++.
Para quienes todavía viven en C++11 o C++14, C++20 marca un buen objetivo de actualización: no solo es un estándar nuevo, sino una oportunidad para revisar arquitectura, APIs y estilo de código con una década de lecciones aprendidas incorporadas al propio lenguaje.
Preguntas frecuentes (FAQ)
1. ¿Cuáles son las principales diferencias entre C++17 y C++20 para un desarrollador de aplicaciones?
Las diferencias más visibles son la llegada de conceptos, módulos y corutinas, junto con rangos y std::span en la biblioteca estándar. También se amplía de forma importante el uso de constexpr y se introduce el operador <=> para comparaciones. En la práctica, esto se traduce en plantillas más claras, mejor soporte para concurrencia y APIs más expresivas.
2. ¿Es obligatorio usar módulos y corutinas al adoptar C++20?
No. C++20 es compatible con el código existente y permite seguir trabajando con includes tradicionales y modelos de concurrencia basados en hilos o futuros. Los módulos y las corutinas son optativos, pero resultan especialmente interesantes en proyectos grandes (por tiempos de compilación) y en servicios de red o procesamiento intensivo de E/S.
3. ¿Qué compiladores soportan hoy C++20 de forma estable?
Las versiones recientes de GCC, Clang y Microsoft Visual C++ ofrecen soporte amplio de C++20 mediante las opciones estándar (-std=c++20 o /std:c++20). Siempre es recomendable consultar la matriz de compatibilidad concreta, pero para la mayoría de aplicaciones de servidor, escritorio o móvil el soporte ya es suficientemente maduro.
4. ¿Merece la pena migrar un proyecto grande a C++20 si funciona bien con C++14 o C++17?
Depende del ciclo de vida del proyecto. Si se espera mantenerlo muchos años, C++20 aporta ventajas en legibilidad, mantenimiento, rendimiento (gracias a nuevas primitivas y optimizaciones) y seguridad en tiempo de compilación. La migración puede hacerse de forma gradual: activar C++20 en el compilador y empezar a introducir nuevas características en módulos o componentes concretos, sin reescribir todo el código de golpe.