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?
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à:
void *
la conversion était impliquée.