web-dev-qa-db-fra.com

Pourquoi std :: ssize () est-il introduit en C ++ 20?

C++ 2 a introduit la fonction libre std::ssize() comme ci-dessous:

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

Une implémentation possible semble utiliser static_cast, Pour convertir la valeur de retour de la fonction membre size() de cl ass C dans son homologue signé.

Puisque la fonction membre size() de C renvoie toujours des valeurs non négatives, pourquoi voudrait-on les stocker dans des variables signées? Au cas où l'on voudrait vraiment, c'est une simple question de static_cast.

Pourquoi std::ssize() est-il introduit en C++ 20?

97
John Z. Li

La justification est décrite dans cet article . Une citation:

Lorsque span a été adopté en C++ 17, il a utilisé un entier signé à la fois comme index et comme taille. Cela devait en partie permettre l'utilisation de "-1" comme valeur sentinelle pour indiquer un type dont la taille n'était pas connue au moment de la compilation. Mais avoir un conteneur STL dont la fonction size () renvoyait une valeur signée était problématique, donc P1089 a été introduit pour "résoudre" le problème. Il a reçu le soutien de la majorité, mais pas la marge de 2 contre 1 nécessaire pour parvenir à un consensus.

Ce document, P1227, était une proposition visant à ajouter les fonctions std :: ssize et membre ssize () non membres. Leur inclusion rendrait certains codes beaucoup plus simples et permettrait d'éviter les non signés indésirables dans les calculs de taille. L'idée était que la résistance à P1089 diminuerait si ssize () était disponible pour tous les conteneurs, à la fois via std :: ssize () et en tant que fonctions membres.

68
Nadav Har'El

Gratuit volé d'Eric Niebler:

'Unsigned types signal that a negative index/size is not sane' était la sagesse qui prévalait lors de la conception de la STL. Mais logiquement, un décompte des choses n'a pas besoin d'être positif. Je veux peut-être garder un nombre dans un entier signé pour indiquer le nombre d'éléments ajoutés ou supprimés d'une collection. Ensuite, je voudrais combiner cela avec la taille de la collection. Si la taille de la collection n'est pas signée, je suis maintenant obligé de mélanger l'arithmétique signée et non signée, qui est une ferme de bogues. Les compilateurs avertissent à ce sujet, mais parce que la conception de la STL force à peu près les programmeurs dans cette situation, l'avertissement est si courant que la plupart des gens le désactivent. C'est dommage car cela cache de vrais bugs.

L'utilisation d'entiers non signés dans les interfaces n'est pas une aubaine pour beaucoup de gens. Si par accident un utilisateur transmet un nombre légèrement négatif à l'API, il devient soudainement un énorme nombre positif. Si l'API a pris le nombre comme signé, elle peut détecter la situation en affirmant que le nombre est supérieur ou égal à zéro.

Si nous limitons notre utilisation d'entiers non signés au twiddling de bits (par exemple, des masques) et que nous utilisons des entiers signés partout ailleurs, les bogues sont moins susceptibles de se produire et plus faciles à détecter lorsqu'ils se produisent.

46
sp2danny