Reflexiones 6 min de lectura 1165 palabras

C++26 no supera la votación de ISO, y los contratos son el motivo

EN
C++26 no supera la votación de ISO, y los contratos son el motivo

Ha pasado algo que, por lo que parece, no había pasado nunca: el borrador de C++26 ha sido rechazado en la votación DIS de ISO, el paso previo a publicar el estándar. Robert Seacord, coordinador del comité de C, lo anunció escuetamente en LinkedIn el 24 de octubre: “Balloting has completed for C++26. Unfortunately it was Disapproved”.

Mateusz Pusz, autor de la biblioteca mp-units y miembro del comité polaco, lo explica con detalle en The result of the C++26 DIS ballot, el sexto artículo de una serie sobre la polémica que hay detrás. Según Seacord, no recuerda que ningún estándar de lenguaje del subcomité SC22 de ISO haya suspendido nunca esta votación, y Daveed Vandevoorde, del grupo de dirección del comité de C++, escribió que ningún borrador anterior de C++ había recibido siquiera un voto en contra.

Los números

Un borrador DIS tiene que cumplir dos condiciones a la vez, y C++26 no ha cumplido ninguna:

CondiciónRequisitoResultado
Votos a favor de los miembros con voto (P)al menos dos tercios12 de 20, un 60%
Votos en contra de todos los países que votaroncomo mucho un 25%9 de 22, un 41%

Hacían falta 14 votos a favor y hubo 12; se permitían 5 en contra y hubo 9. Cualquiera de las dos cosas por separado habría bastado para tumbarlo.

Votaron en contra Dinamarca, Finlandia, Irán, Italia, Japón, Luxemburgo, Rumanía, España y Suecia, todos con comentarios técnicos. Francia e Irlanda se abstuvieron, pero también enviaron comentarios. Polonia y Estados Unidos se abstuvieron. Los comentarios todavía no son públicos: las normas de ISO dan un plazo de 12 semanas para publicar el informe completo, así que como muy tarde llegarán a mediados de enero de 2027.

El motivo: los contratos

Aunque los comentarios no se conocen aún, Pusz está convencido de que los nueve votos en contra son por los contratos, y tiene argumentos: toda la oposición registrada antes de la votación iba en esa dirección. Las dos objeciones que se expusieron en el pleno que envió C++26 a votación eran sobre contratos, varios países ya habían pedido quitarlos en la fase anterior, y un documento, P4238R1, pedía expresamente a los comités nacionales que votaran en contra por el diseño de los contratos y por cómo se había aprobado.

Los contratos permiten escribir en la firma de una función qué tiene que cumplirse antes y después de llamarla:

#include <cmath>

double checked_sqrt(double x)
    pre(x >= 0.0)
    post(r: r >= 0.0)
{
    const double root = std::sqrt(x);
    contract_assert(!std::isnan(root));
    return root;
}

pre es una precondición, post una postcondición sobre el valor devuelto y contract_assert una comprobación dentro del cuerpo. La idea gusta a casi todo el mundo: es documentación que el compilador entiende y que, si se activan las comprobaciones, no puede quedarse desfasada sin que nadie se entere, como pasa con un comentario. Pusz lo resume bien: los concepts ya hacen eso con los tipos que acepta una función en tiempo de compilación, y los contratos harían lo mismo con los valores en tiempo de ejecución.

El problema está en los detalles. El código no decide si cada comprobación se ejecuta ni qué pasa si falla. El borrador define cuatro semánticas, ignore, observe, enforce y quick-enforce, y deja la elección a la implementación; en GCC 16 se elige con una opción del compilador. Buena parte de la discusión es justo esa: si un contrato es una comprobación que la compilación puede eliminar o una garantía en la que el programa puede confiar. También se discute qué puede salir mal dentro del propio predicado y si había suficiente experiencia en producción antes de estandarizarlo. Además, los contratos ya se quitaron de C++20, así que no es la primera vez que se quedan fuera.

Lo que queda bloqueado

Lo delicado es que el rechazo no afecta sólo a los contratos. Con ellos se quedan en un borrador sin aprobar otras novedades muy esperadas de C++26:

  • Reflexión en tiempo de compilación.
  • std::execution, el nuevo modelo para programación asíncrona.
  • El endurecimiento de la biblioteca estándar (library hardening), que precisamente se apoya en parte en los contratos.

Qué puede pasar ahora

Las normas de ISO prevén cuatro salidas tras un DIS rechazado: un nuevo borrador DIS con una votación más corta, de ocho semanas; un nuevo borrador de comité para comentarios; publicarlo como especificación técnica; o cancelar el proyecto. Ninguna tiene fecha todavía.

La próxima reunión del comité de C++ es en Búzios, Brasil, del 16 al 21 de noviembre, y las posturas están divididas:

  • Quitar los contratos para que el resto salga cuanto antes. J. Daniel García, uno de los autores de P4238R1, lo dice así: “la solución a corto plazo es sencilla, quitar una funcionalidad problemática y el resto del estándar se aprobará muy probablemente”. Vandevoorde también recomendará quitarlos, con ajustes para conservar el endurecimiento de la biblioteca.
  • Volver a votar sin cambiar los contratos. Lo propone P4433R0, firmado por dieciséis defensores de los contratos, que además sostienen que quitarlos no sería rápido, porque es un cambio grande y obligaría a rediseñar el endurecimiento de la biblioteca.
  • Pasarlos a una especificación técnica o a un documento aparte, como pedían algunos países.

Incluso el nombre está en el aire. Si el estándar se publica en 2027, Vandevoorde cree que “C++27 tendría sentido”. No sería raro: C++23 se publicó tan tarde que oficialmente es ISO/IEC 14882:2024. Mientras tanto, el estándar vigente sigue siendo C++23.

Y para el código de hoy

Los compiladores implementan el borrador de trabajo, y la votación no cambia lo que ya incluyen. GCC 16 acepta -std=c++26 e implementa los contratos como parte de su soporte experimental, y Clang tiene -std=c++2c, aunque su implementación de los contratos aún no se ha integrado. Quien ya use funcionalidades de C++26 no tiene que deshacer nada por ahora, pero sí debe saber que está usando un borrador, y que si usa pre, post o contract_assert con GCC 16, depende justo de la parte que está en disputa.

Lo que me llevo

Esta historia me parece interesante más allá de C++. Muestra lo difícil que es añadir algo tan aparentemente sencillo como “comprobar que el argumento es positivo” a un lenguaje con décadas de código detrás, muchos compiladores y usuarios con necesidades opuestas: para unos, una comprobación tiene que poder desactivarse sin coste; para otros, si se puede desactivar, no es una garantía.

Me quedo también con una reflexión del propio Pusz sobre cómo funcionan estos procesos: el voto de Polonia estuvo a punto de no existir porque no se llegaba al quórum, en parte porque había miembros que habían cambiado de trabajo y no respondían. Su consejo vale para cualquier comité: si formas parte de uno, vota, y si ya no puedes participar, pide que te den de baja.

Y comparto su deseo: que los contratos salgan con un diseño mejor si hace falta, pero que el resto de C++26 no tenga que esperar por ellos.

Fuente: The result of the C++26 DIS ballot, Mateusz Pusz, Train IT.

Etiquetas