【问题标题】:Why does g++ 4.x allows implicit conversion of nullptr to another types when passed as parameter but > 5.x dont?为什么 g++ 4.x 在作为参数传递时允许将 nullptr 隐式转换为另一种类型,但 > 5.x 不允许?
【发布时间】:2019-01-10 19:18:46
【问题描述】:

我的理解是,nullptr 无法隐式转换为其他类型。但后来我“发现”它可以转换为布尔值。 问题是,我可以看到它在 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++11 gcc g++ nullptr


    【解决方案1】:

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

    对于直接初始化,std::nullptr_t 类型的纯右值可以 转换为bool 类型的纯右值;结果是假的。

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

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

    我假设这条规则的目的是为您编写的确切代码引发错误:bool 是预期的,并且提供了一个空指针常量;测试一个空指针常量的布尔值并不是很有意义,因为它无论如何只有一种状态。

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

    代码可能是:

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

    或者您可以添加一个接受std::nullptr_tf 的重载。

    【讨论】:

      猜你喜欢
      • 2012-02-10
      • 2013-07-07
      • 2015-03-12
      • 1970-01-01
      • 2021-10-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多