このプログラムを考えてみましょう:
#include <cstdint>
using my_time_t = uintptr_t;
int main() {
const my_time_t t = my_time_t(nullptr);
}
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
しかし、clang(9.0.1)とgcc(9.2.1)は、エラーなしでこのコードを「食べ」ます。
MSVCの動作は好きですが、標準で確認されていますか?言い換えれば、それはclang/gccのバグですか、これがgcc/clangからの正しい動作であるという標準を解釈することは可能ですか?
すべて標準に準拠しています(C++のドラフトn4659を参照)。
nullptr
は、[Lex.nullptr]で次のように定義されています。
ポインタリテラルは、キーワードnullptrです。これは、タイプstd :: nullptr_tのprvalueです。 [注:...、このタイプのprvalueはnullポインター定数であり、nullポインター値またはnullメンバーポインター値に変換できます。]
ノートが非規範的である場合でも、これにより、標準ではnullptr
がnull pointer値に変換されることが期待されることが明らかになります。
後で[conv.ptr]で見つけます:
NULLポインター定数は、値がゼロの整数リテラルまたはstd :: nullptr_tタイプのprvalueです。 nullポインター定数はポインター型に変換できます。 ....整数型のnullポインター定数は、型std :: nullptr_tのprvalueに変換できます。
ここでも、標準で必要なのは、0
をstd::nullptr_t
に変換でき、nullptr
を任意のポインター型に変換できることです。
私の見解では、nullptr
を直接整数型に変換できるかどうかについて、標準には要件がないということです。その時点から:
void *
変換が含まれているかのように動作します。