隐式生成的成员和noexcept

时间:2012-02-07 16:41:16

标签: c++ c++11 language-lawyer

我最近开始添加新的noexcept规范,以尽可能地移动构造函数/赋值。现在我开始想知道隐式生成的成员函数的异常规范是什么样的。由于具有noexcept移动函数允许使用更有效的代码路径(例如,在调整vector时),我希望尽可能将它们声明为noexcept。我在理解标准对此有何看法时遇到了问题,因此尝试使用g ++ 4.6中的以下代码(使用-std=c++0x)来掌握它:

struct foobar{};
int main()
{
    foobar a, b;
    std::cout<<std::boolalpha
             <<noexcept(foobar())<<", "<<noexcept(foobar(a))<<", "
             <<noexcept(a = b)   <<", "<<noexcept(a = std::move(b))<<", "
             <<noexcept(foobar(std::move(a)))<<std::endl;
}

这给了我一个True, True, True, False, False的输出,意思是默认和复制构造函数/赋值noexcept,而移动操作不在哪里。

现在我的问题:

在什么情况下隐式生成(或默认)成员函数声明为noexcept?此外,foobar正确或仅仅是gcc4.6中的编译器错误的行为是否存在?

1 个答案:

答案 0 :(得分:18)

库错误 - 它在gcc 4.7中显示true, true, true, true, true

错误是生成的移动构造函数不是noexcept,但std::move未标记为noexcept,我们可以通过其他测试看到:

std::cout << noexcept(a = static_cast<foobar&&>(b)) << ", "  // true
          << noexcept(foobar(static_cast<foobar&&>(b))) << ", " // true
          << noexcept(std::move(b)) << std::endl;   // false

gcc 4.6中的大多数库函数都不是noexcept-correct,这已在gcc 4.7中解决,


至于无限制生成的成员函数是不存在的,这在§15.4/ 14中有记载。基本上,如果它需要调用的所有函数都是noexcept,则为noexcept

  

隐式声明的特殊成员函数(第12条)应具有异常规范。如果是f    隐式声明的默认构造函数,复制构造函数,移动构造函数,析构函数,复制赋值   运算符或移动赋值运算符,其隐式异常 - 规范指定 type-id T当且仅当      如果由T的隐式定义直接调用的函数的 exception-specification 允许f; f应该           允许所有异常,如果它直接调用的任何函数允许所有异常,f将不允许异常          如果它直接调用的每个函数都不允许例外。