考虑以下代码:
#includevoid f( std::shared_ptr ) {} 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,它接受所有变体,除了f(i);
c ++ 11和c ++ 14模式PPS用clang 3.7检查,它拒绝除c ++ 11和c ++ 14中的文字0之外的所有变体模式
这是一个gcc bug.缺陷报告903:依赖于值的整数空指针常量,它是针对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 templatevoid g() { f(0*N); // calls #2; used to call #1 }
以下gcc错误报告[C++ 11] [DR 903]零值整数常量表达式应该更喜欢转换为指针,这表明gcc团队最初认为这是C++ 17的更改但后来将其更改为有效C++ 11.
我们可以在gcc(6.0)的头版修订版中看到这是固定的(实时查看),并为clang所做的所有案例生成诊断:
error: could not convert '(1 - 1)' from 'int' to 'std::shared_ptr' f( 1 - 1 ); // compiles fine in gcc, fails in clang ~~^~~ error: could not convert 'i' from 'const int' to 'std::shared_ptr ' f( i ); // fails to compile in gcc and clang ^ error: could not convert '(0 - 0)' from 'int' to 'std::shared_ptr ' f( i - 0 ); // compiles fine in gcc, fails in clang ~~^~~
因为空指针常量不仅定义为值为0的编译时整型常量,而且定义为值为零的整数文字(std::nullptr_t
当然也可以是类型的prvalue ).C++ 14(N4140),4.10/1.
实际上,只有第一行f(0)
应该编译,所有其他的应该至少引起来自符合编译器的诊断消息.