C++ 编译器何时会为方法推断出 noexcept?

When does a C++ compiler infer noexcept for a method?

我只是注意到我的一个 std::vector<Foo> 在调整大小时正在复制而不是移动它的元素 - 尽管 Foo 有一个 move ctor:

class Foo {
    // ...
    Foo(Foo&& other) : id_(other.id_), ptr_(other.ptr_), flag(other.flag)
    {
        other.flag = false;
    };
    // ...
    int   id_; 
    void* ptr_; 
    bool  flag;
}

然后我读到:

Resize on std::vector does not call move constructor

这提醒我 std::vector 只有在声明元素的移动构造函数 noexcept 时才会使用移动构造。当我添加 noexcept 时,会调用移动 ctor。

我的问题是:为什么给定 move ctor 的代码,编译器没有确定它是 noexcept?我的意思是,它可以知道不能抛出异常这一事实。另外,推断 noexcept 是标准不允许的,还是不是由我的特定编译器完成的?

我在 GNU/Linux.

上使用 GCC 5.4.0

tl;dr:不允许编译器推断 noexcept

Why, given the move ctor's code, does the compiler not determine it to be noexcept?

因为 noexcept 规范是根据声明而不是定义来确定的。这类似于 const 规范的工作方式。不允许编译器将函数确定为 const,即使它的实现不修改任何成员。

is inferring noexcept disallowed by the standard

据我了解,是的:

[except.spec] ... absence of an exception-specification in a function declarator other than that for a destructor (12.4) or a deallocation function (3.7.4.2) denotes an exception specification that is the set of all types.

推断除所有类型的集合之外的其他东西将与此规则相矛盾。当然,当编译器可以证明不会抛出异常时,它可以根据 as-if 规则优化掉任何堆栈展开代码,但这种优化不会影响 SFINAE 自省。


关于引入 noexcept(auto) 的可能性 discussion,这将是一种 显式 让编译器推断 noexcept 规范的方法。