c++ c++20

¿Por qué se introduce std:: ssize() en C++ 20?



c++20 (2)

C++20 introdujo la función libre std::ssize() como se muestra a continuación:

template <class C> constexpr auto ssize(const C& c) -> std::common_type_t<std::ptrdiff_t, std::make_signed_t<decltype(c.size())>>;

Una posible implementación parece usar static_cast , para convertir el valor de retorno de la función miembro size() de cl ass C en su contraparte firmada.

Dado que la función de miembro size() de C siempre devuelve valores no negativos, ¿por qué alguien querría almacenarlos en variables con signo? En caso de que uno realmente quiera, es una cuestión de simple static_cast .

¿Por qué se introduce std::ssize() en C ++ 20?


El razonamiento se describe en este documento . Una cita:

Cuando se adoptó span en C ++ 17, utilizó un entero con signo tanto como índice como tamaño. En parte esto fue para permitir el uso de "-1" como valor de centinela para indicar un tipo cuyo tamaño no se conocía en el momento de la compilación. Pero tener un contenedor STL cuya función size () devolviera un valor firmado era problemático, por lo que se introdujo P1089 para "solucionar" el problema. Recibió apoyo mayoritario, pero no el margen de 2 a 1 necesario para el consenso.

Este documento, P1227, fue una propuesta para agregar funciones std :: ssize y ssize () de miembros no miembros. La inclusión de estos haría que ciertos códigos fueran mucho más sencillos y permitiría evitar la no firma no deseada en los cálculos de tamaño. La idea era que la resistencia a P1089 disminuiría si ssize () estuviera disponible para todos los contenedores, tanto a través de std :: ssize () como de funciones miembro.


stolen de Eric Niebler:

''Unsigned types signal that a negative index/size is not sane'' fue lo que prevaleció cuando se diseñó la STL por primera vez. Pero lógicamente, una cuenta de cosas no necesita ser positiva. Es posible que desee mantener un recuento en un entero con signo para indicar el número de elementos agregados o eliminados de una colección. Entonces me gustaría combinar eso con el tamaño de la colección. Si el tamaño de la colección no está firmado, ahora estoy obligado a mezclar aritmética firmada y no firmada, que es una granja de errores. Los compiladores advierten sobre esto, pero debido a que el diseño de STL obliga a los programadores a esta situación, la advertencia es tan común que la mayoría de la gente la desactiva. Eso es una pena porque esto esconde errores reales.

El uso de entradas no firmadas en las interfaces no es la ventaja que mucha gente piensa que es. Si por accidente, un usuario pasa un número ligeramente negativo a la API, de repente se convierte en un gran número positivo. Si la API hubiera tomado el número como firmado, entonces puede detectar la situación afirmando que el número es mayor o igual a cero.

Si restringimos nuestro uso de entradas no firmadas a cambios de bits (por ejemplo, máscaras) y usamos entradas firmadas en cualquier otro lugar, es menos probable que ocurran errores y que sean más fáciles de detectar cuando ocurren.