c++ - is_nothrow_default_constructible 带有 noexcept(false) 默认构造函数

标签 c++ language-lawyer

当我偶然发现一个奇怪的行为时,我试图static_assert 一些类型特征以确保自定义类型具有预期的noexcept 保证。上面的简化代码段说明了这个问题:

struct DefaultOnly
{
    constexpr DefaultOnly() noexcept(false) {};
};

static_assert(std::is_nothrow_default_constructible_v<DefaultOnly>);

对于这个简单的类型,GCC 8 通过了 static_assert 而 Clang 7 没有通过。我不知道哪个编译器是正确的。这是其中一个编译器中的错误,还是nothrow default constructible 的标准定义足够灵活,以至于两个编译器都根据对标准的解释产生有效但不同的结果?

最佳答案

这个问题与具有 noexcept 规范的构造函数没有直接关系,而是在 noexcept 起作用时编译器如何处理常量表达式

如果您将构造函数声明为 no constexpr,那么两个编译器都会按预期工作:

struct DefaultOnly
{
    DefaultOnly() noexcept(false) {};
};
static_assert(std::is_nothrow_default_constructible_v<DefaultOnly>);

回到 C++11,常量表达式noexcept 规范不敏感,但它经历了直到 C++17 的更改。到目前为止,constexpr 函数受 noexcept 规范影响。

Clang 按预期工作。

以下代码将显示与您的行为相同的行为:

constexpr int foo() noexcept(false) { return 0;}
static_assert(noexcept(foo()));

作为引用,这是 GCC-87603 的摘录报告:

CWG 1129 (which ended up in C++11) added a special case to noexcept for constant expressions, so that:

constexpr void f() {} static_assert(noexcept(f()));

CWG 1351 (which ended up in C++14) changed the wording significantly, but the special case remained, in a different form.

P0003R5 (which ended up in C++17) changed the wording again, but the special case was removed (by accident), so now:

constexpr void f() {} static_assert(!noexcept(f()));

According to Richard Smith in LLVM 15481, CWG discussed this but decided to keep the behavior as-is. Currently, clang does the right thing for C++17 (and fails for C++14 and C++11, on purpose). g++, however, implemented the special case for C++11 already, but not the change for C++17. Currently, icc and msvc seem to behave like g++.

另见 GCC-86044GCC-88453更具体地等同于您的情况。

关于c++ - is_nothrow_default_constructible 带有 noexcept(false) 默认构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53900608/

相关文章:

c++ - 我想看一个函数名称在嵌套名称说明符中被忽略的示例

c++ - 下面的第一个片段编译,但第二个没有。为什么?

c++ - decltype(foo(1)) 应该实例化 constexpr 函数模板 foo 吗?

c++ - 在 char 数组中查找最多 6 个连续 0 位的最快方法

c++ - 如何在Qt中使用STL算法?

c++ - 序列号 : write() throttling?

c++ - 什么是 C++ 中的 ->* 运算符?

C++使变量类型取决于用户输入

c++ - 关于char的签名问题

c++ - std::stoi 实际上可以安全使用吗?