Conversion from integral constant expression to null-pointer

折月煮酒 提交于 2019-12-04 23:33:28

This is a gcc bug. Defect report 903: Value-dependent integral null pointer constants which is a defect report against C++11(it has CD3 status), makes it so that only an integer literal 0 is considered a null pointer constant.

It changed section 4.10 [conv.ptr] paragraph 1 amongst other changes from:

A null pointer constant is an integral constant expression (5.19 [expr.const]) prvalue of integer type that evaluates to zero [...]

to:

A null pointer constant is an integer literal (2.14.2 [lex.icon]) with value zero [...]

This is listed as an incompatibility against C++03, from section C.2.2 Clause 4: standard conversions [diff.cpp03.conv] which says:

Change: Only literals are integer null pointer constants
Rationale: Removing surprising interactions with templates and constant expressions
Effect on original feature: Valid C++ 2003 code may fail to compile or produce different results in this International Standard, as the following example illustrates:

void f(void *); // #1
void f(...); // #2
template<int N> void g() {
  f(0*N); // calls #2; used to call #1
}

The following gcc bug report [C++11] [DR 903] zero-valued integer constant expression should prefer conversion to pointer shows that the gcc team originally thought this was a C++17 change but later changed it to be in effect in C++11.

We can see in the head revision of gcc(6.0) this is fixed (see it live) and produces a diagnostic for all the cases clang does:

error: could not convert '(1 - 1)' from 'int' to 'std::shared_ptr<int>'
 f( 1 - 1 );           // compiles fine in gcc, fails in clang
    ~~^~~

error: could not convert 'i' from 'const int' to 'std::shared_ptr<int>'
 f( i );               // fails to compile in gcc and clang
      ^

error: could not convert '(0 - 0)' from 'int' to 'std::shared_ptr<int>'
 f( i - 0 );           // compiles fine in gcc, fails in clang
    ~~^~~

Because a null pointer constant is defined not just as a compile-time integral constant with value 0, but as an integer literal with value zero (or as a prvalue of type std::nullptr_t, of course). C++14 (N4140), 4.10/1.

So actually, only the first line f(0) should compile, all the other ones should provoke at least a diagnostic message from a conforming compiler.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!