请考虑以下代码:
#include <memory>
void f( std::shared_ptr<int> ) {}
int main()
{
f( 0 ); // compiles fine in gcc and clang
f( 1 - 1 ); // compiles fine in gcc, fails in clang
constexpr int i = 0;
f( i ); // fails to compile in gcc and clang
f( i - 0 ); // compiles fine in gcc, fails in clang
}
为什么只有f( i )
无法编译,尽管i
应该被评估为值为0的编译时常量?
使用g ++ v 5.1.0检查PS,它在c ++ 11和c ++ 14模式下接受除f(i);
以外的所有变体
使用clang 3.7检查PPS,它拒绝除c ++ 11和c ++ 14模式中的文字0之外的所有变体
答案 0 :(得分:20)
这是一个gcc错误。 Defect report 903: Value-dependent integral null pointer constants 这是针对C ++ 11的缺陷报告(它具有CD3状态),使得只有整数文字0
被视为空指针常量。
更改了4.10
[conv.ptr]段1
部分以及其他更改:
空指针常量是整数类型的整数常量表达式(5.19 [expr.const])prvalue,其计算结果为零[...]
为:
空指针常量是一个整数文字(2.14.2 [lex.icon]),其值为零[...]
这被列为与C ++ 03的不兼容,来自C.2.2
条款第4条:标准转换 [diff.cpp03.conv] ,其中包含:
更改:只有文字是整数空指针常量
理由:删除模板和模板的令人惊讶的交互 常数表达 对原始功能的影响:有效的C ++ 2003代码可能无法编译或 在本国际标准中产生不同的结果 以下示例说明:void f(void *); // #1 void f(...); // #2 template<int N> void g() { f(0*N); // calls #2; used to call #1 }
以下gcc错误报告[C++11] [DR 903] zero-valued integer constant expression should prefer conversion to pointer显示gcc团队最初认为这是C ++ 17更改,但后来将其更改为在C ++ 11中生效。
我们可以在gcc( 6.0 )的头版修订版中看到这是固定的( see it live ),并为clang所做的所有案例生成诊断:
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
~~^~~
答案 1 :(得分:6)
因为空指针常量不仅定义为值为0的编译时整数常量,而且定义为值为零的整数 literal (或作为prvalue)当然是std::nullptr_t
类型的。 C ++ 14(N4140),4.10 / 1。
实际上,只有第一行f(0)
应该编译,所有其他行应该至少引起来自符合编译器的诊断消息。