为什么 g++ 4.x 允许在作为参数传递时将 nullptr 隐式转换为其他类型,但 > 5.x 不允许?

Why does g++ 4.x allows implicit conversion of nullptr to another types when passed as parameter but > 5.x dont?

我的理解是,nullptr 无法隐式转换为其他类型。但是后来我"found"认为它可以转换为bool。 问题是,我可以看到它在 GCC 4.x 上被转换为 bool,但它在 GCC 上抱怨 > 5.X

#include <iostream>
bool f(bool a){
    return !a;
}
// Type your code here, or load an example.
int main() {
    return f(nullptr);
}

在 >5.x 我得到

<source>: In function 'int main()':

<source>:7:21: error: converting to 'bool' from 'std::nullptr_t' requires direct-initialization [-fpermissive]
     return f(nullptr);

             ^

<source>:2:6: note:   initializing argument 1 of 'bool f(bool)'
 bool f(bool a){

      ^
Compiler returned: 1

我在 GCC 5.X 的发行说明中找不到任何可以解释这一点的内容。

可以在这里观察到: https://godbolt.org/g/1Uc2nM

有人可以解释为什么版本之间存在差异以及此处应用的规则。

规则可以在C++17中找到[conv.bool]/1:

For direct-initialization, a prvalue of type std::nullptr_t can be converted to a prvalue of type bool; the resulting value is false.

函数参数的初始化是copy-initialization,不是direct-initialization。如果您不熟悉这个话题; C++中的初始化上下文可以分为这两种类,还有一些操作只能发生在直接初始化中。

在C++14中加入了对直接初始化的限制,这可以解释g++版本之间的差异。

我假设此规则的目的是针对您编写的确切代码引发错误:需要 bool 并且提供了空指针常量;测试空指针常量的布尔值意义不大,因为它只有一种状态。

记住 nullptr 不是指针;如果代码明确请求这样的转换,它是可以隐式转换为空指针的东西。添加它的全部原因是修复 0 被用作空指针常量,并无意中匹配其他模板或重载的问题。

代码可以是:

return f(static_cast<bool>(nullptr));

或者你可以添加一个 f 的重载来接受 std::nullptr_t.