web-dev-qa-db-ja.com

nullptrをuintptr_tに変換できますか?異なるコンパイラは同意しません

このプログラムを考えてみましょう:

#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からの正しい動作であるという標準を解釈することは可能ですか?

10
user1244932

すべて標準に準拠しています(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に変換できます。

ここでも、標準で必要なのは、0std::nullptr_tに変換でき、nullptrを任意のポインター型に変換できることです。

私の見解では、nullptr直接整数型に変換できるかどうかについて、標準には要件がないということです。その時点から:

  • MSVCには厳密な読み取りがあり、変換を禁止します
  • Clangとgccは、中間のvoid *変換が含まれているかのように動作します。
0
Serge Ballesta