当前位置:  开发笔记 > 编程语言 > 正文

constexpr是否暗示noexcept?

如何解决《constexpr是否暗示noexcept?》经验,为你挑选了2个好方法。



1> Shafik Yaghm..:

不可能不是这种情况,因为并非constexpr函数的每个inovocation都必须能够被评估为核心常量表达式的子表达式.我们只需要一个允许这个的参数值.因此,只要我们有一个不调用该分支的参数值,constexpr函数就可以包含一个throw语句.

这在C++ 14标准草案章节7.1.5constexpr说明符[dcl.constexpr]中有所介绍,它告诉我们constexpr函数允许的内容:

constexpr函数的定义应满足以下约束:

它不应是虚拟的(10.3);

其返回类型应为字面类型;

每个参数类型都应是文字类型;

它的函数体应为= delete,= default或不包含的复合语句

asm-definition,

一个goto声明,

尝试块,或

非文字类型或静态或线程存储持续时间的变量的定义,或者不执行初始化的定义.

我们可以看到它并不禁止throw,事实上禁止很少,因为对constexpr函数提议的放宽限制成为C++ 14的一部分.

下面我们看到规则说如果至少存在一个参数值,则constexpr函数是格式良好的,这样它就可以被计算为核心常量表达式的子表达式:

对于非模板,非默认的constexpr函数或非模板,非默认的,非继承的constexpr构造函数,如果不存在参数值,则调用函数或构造函数可以是核心常量的计算子表达式表达式(5.19),程序不正确 ; 无需诊断.

在本段下面我们有以下示例,其中显示了此案例的完美示例:

constexpr int f(bool b)
  { return b ? throw 0 : 0; } // OK
constexpr int f() { return f(true); } // ill-formed, no diagnostic required

所以我们期望以下示例的输出:

#include 

constexpr int f(bool b)   { return b ? throw 0 : 0; } 

int main() {
    std::cout << noexcept( f(1) ) << "\n" 
              << noexcept( f(0) ) << "\n" ; 
}

是(看到它与gcc一起生活):

 0
 1

通过webcompiler的 Visual Studio 也会产生相同的结果.正如hvd所指出的那样,clang有一个错误,如bug报告所述,noexcept应检查表达式是否为常量表达式.

缺陷报告1129

缺陷报告1129:constexpr函数的默认值nothrow询问相同的问题:

不允许constexpr函数通过异常返回.这应该被识别,并且声明constexpr而没有显式异常规范的函数应该被视为声明为noexcept(true)而不是通常的noexcept(false).对于声明constexpr而没有显式异常规范的函数模板,当且仅当在给定实例化上遵守constexpr关键字时,才应将其视为noexcept(true).

而回应是:

前提是不正确的:只有在需要常量表达式的上下文中调用constexpr函数时才禁止异常.用作普通函数,它可以抛出.

并修改了5.3.7 [expr.unary.noexcept]第3段子弹1(另外强调指出):

一个可能被评估的函数,成员函数,函数指针或成员函数指针的call80,它没有非抛出异常规范(15.4 [except.spec]),除非调用是一个常量表达式(5.20 [expr.常量]),



2> skypjack..:

有人说的noexcept是:

如果表达式包含对任何类型的没有非抛出异常规范的函数的调用,则结果为false,除非它是常量表达式.

而且,关于constexpr,确实如此:

对于常量表达式,noexcept运算符始终返回true

在任何情况下,它似乎都没有暗示说明constexpr符强制包含noexcept表达式的说明符,正如有人在评论中显示的反例并且您也验证了.

总之,从文档,有大约之间的关系如下有趣的说明noexceptconstexpr:

因为noexcept运算符总是为常量表达式返回true,所以它可以用于检查constexpr函数的特定调用是否采用常量表达式分支

编辑:GCC的例子

感谢@hvd对GCC关于我的最后一句话的有趣评论/例子.

constexpr int f(int i) {
    return i == 0 ? i : f(i - 1);
}

int main() {
    noexcept(f(512));
    return noexcept(f(0)) == noexcept(f(0));
}

上面的代码返回0,并警告该语句noexcept(f(512))无效.
在评论那个据说没有效果的陈述时,返回值会变为1.

编辑:已知的铿锵声

再次感谢@hvd也提供了这个链接,这是关于clang中关于代码中提到的代码的一个众所周知的错误.

从错误报告中引用:

在C++的书中,[expr.unary.noexcept] p3:

"如果在潜在评估的上下文中,表达式将包含对函数,成员函数,函数指针或不具有非抛出异常规范的成员函数指针的潜在评估调用,则noexcept运算符的结果为false (15.4),除非调用是常数表达式(5.19) ".

我们没有实现最后一个短语.

推荐阅读
谢谢巷议
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有