web-dev-qa-db-fra.com

Nullptr peut-il être converti en uintptr_t? Différents compilateurs ne sont pas d'accord

Considérez ce programme:

#include <cstdint>
using my_time_t = uintptr_t;

int main() {
    const my_time_t t = my_time_t(nullptr);
}

Il n'a pas réussi à compiler avec msvc v19.24:

<source>(5): error C2440: '<function-style-cast>': cannot convert from 'nullptr' to 'my_time_t'
<source>(5): note: A native nullptr can only be converted to bool or, using reinterpret_cast, to an integral type
<source>(5): error C2789: 't': an object of const-qualified type must be initialized
<source>(5): note: see declaration of 't'

Compiler returned: 2

mais clang (9.0.1) et gcc (9.2.1) "mangent" ce code sans aucune erreur.

J'aime le comportement MSVC, mais est-il confirmé par la norme? En d'autres termes, est-ce un bogue dans clang/gcc ou il est possible d'interpréter standard que c'est le bon comportement de gcc/clang?

10
user1244932

Tous sont conformes à la norme (réf. Draft n4659 pour C++).

nullptr est défini dans [Lex.nullptr] comme:

Le littéral du pointeur est le mot-clé nullptr. C'est une prvalue de type std :: nullptr_t. [Remarque: ..., une prvalue de ce type est une constante de pointeur nul et peut être convertie en valeur de pointeur nul ou en valeur de pointeur de membre nul.]

Même si les notes ne sont pas normatives, celle-ci indique clairement que pour le standard, nullptr devrait être converti en une valeur nulle pointeur.

Nous trouvons plus tard dans [conv.ptr]:

Une constante de pointeur null est un littéral entier avec la valeur zéro ou une prvalue de type std :: nullptr_t. Une constante de pointeur nul peut être convertie en un type de pointeur; .... Une constante pointeur nul de type intégral peut être convertie en une valeur pr de type std :: nullptr_t.

Là encore, ce qui est exigé par la norme est que 0 peut être converti en std::nullptr_t et que nullptr peut être converti en n'importe quel type de pointeur.

Ma lecture est que la norme n'a aucune exigence quant à savoir si nullptr peut être directement converti en un type intégral ou non. À partir de là:

  • MSVC a une lecture stricte et interdit la conversion
  • Clang et gcc se comportent comme si un intermédiaire void * la conversion était impliquée.
0
Serge Ballesta