C++20 – std::bit_cast

Bonjour à tous !

Après un petit mois d’absence, je vous propose aujourd’hui un petit article traitant d’une nouveauté à venir de C++20 : std::bit_cast.

reinterpret_cast ?

reinterpret_cast  est l’un des opérateurs de conversion en C++. Celui-ci est assez mal compris par les développeurs débutants qui s’attendent à pouvoir faire des choses telles que :

Si ce code peut sembler correct, il ne l’est pas. Il s’agit ici d’un undefined behavior résultant des règles de strict pointer aliasing (notez que cette règle est aussi valide pour les unions contrairement au C).

Il existe un certain nombre d’opérations définies par le standard qu’il est possible de faire avec reinterpret_cast. Dans l’exemple ci-dessus, la seule opération définie sur d est de le reconvertir en son type initial, à savoir std::int64_t*. Déréférencer d est un comportement indéterminé. Je vous laisse d’ailleurs une citation de la doc de MSDN :

The result of a  reinterpret_cast cannot safely be used for anything other than being cast back to its original type. Other uses are, at best, nonportable.

Alors comment faire ? La solution standard avant C++20 est d’utiliser std::memcpy :

C’est assez lourd à l’écriture et en plus,  std::memcpy n’est pas constexpr, ce qui empêche de faire ce genre de conversion à la compilation. Notez ici qu’on a la nécessité d’avoir un type de destination qui est default-constructible, ou tout du moins de le construire avant l’appel de  std::memcpy.

std::bit_cast

La p0476 propose donc  std::bit_cast qui permettrait de simplifier ce genre de manipulation.

Notez d’ailleurs que  std::bit_cast est une fonction de la bibliothèque standard et non pas un nouvel opérateur de conversion. Elle est définie dans le nouveau header <bit>.

std::bit_cast n’est pour le moment supporté par aucun compilateur, notamment parce qu’il n’est pas possible d’en implémenter une version  constexpr sans que le compilateur fasse un traitement spécifique. Cela étant, elle permet d’effectuer des réinterprétations de séquences de bits sans tomber dans l’undefined behavior :

Cette fonction n’est utilisable (et ne participe à la résolution de surcharge) que si la taille du type d’entrée est égale à celle du type de sortie et que les deux types sont copiables de façon triviale (TriviallyCopyable).

Voilà donc pour cet ajout mineur à venir pour C++20. Je vous dis à bientôt pour un nouvel article :).

Références et ressources

%d bloggers like this: