【问题标题】:Does disabling support for exceptions also disable support for `std::move_if_noexcept`?禁用对异常的支持是否也会禁用对`std::move_if_noexcept`的支持?
【发布时间】:2014-12-08 23:04:32
【问题描述】:

一些商店(例如,一些视频游戏开发团队)在其构建环境中禁用对异常的支持。禁用异常后,开发人员将没有理由声明他们的移动操作noexcept(假设这样的代码甚至可以编译)。但是标准库实现应该在实现某些操作时调用std::move_if_noexcept(例如,std::vector::push_back)。标准库实现是否通常在编译期间检查异常是否被禁用,如果是,使用std::move 而不是std::move_if_noexcept?当异常被禁用时,编译器是否会导致 std::is_nothrow_move_constructible 为所有类型返回 true?或者禁用对异常的支持是否会导致 std:move_if_noexcept 无法启用移动操作的意外副作用?

我对实践中发生的事情很感兴趣。我知道禁用对异常的支持会使我们脱离 C++ 标准的范畴。

【问题讨论】:

  • 这不是很容易自己测试吗?
  • @KerrekSB:我当然可以为自己可以访问的编译器测试它,但是我可以访问的编译器的数量是有限的,而且我认为人们在经常禁用异常的环境中工作早就知道答案了。至于测试是否“容易”……需要对标准库实现进行一些搜索才能找出发生了什么,而这并不总是简单的工作。
  • libc++ 和 libstdc++ 似乎都不对编译器是否禁用异常感兴趣,因此您不会神奇地让所有动作都成为这些库中的动作。像std::is_nothrow_constructible 这样的特征用noexcept 运算符表示,这通常与环境是否实际支持异常无关。就 trait 而言,它只是函数声明的抽象部分。
  • 尽管看起来并非如此,但当异常被禁用时,编译器似乎应该隐式地使所有内容都为“noexcept”。对于大多数编译器供应商来说,这应该是一个非常简单的修复方法。你应该让 GCC 和 Clang 的人知道这一点,如果它不在他们的待办事项列表上。

标签: c++ exception c++11 move-semantics


【解决方案1】:

此代码在 GCC 4.9 和 clang 3.5 上输出 false true false true,无论是否启用异常:

void foo() {}
void bar() noexcept {}
void foo2() noexcept(noexcept(foo())) {}
void bar2() noexcept(noexcept(bar())) {}

int main() {
    std::cout << std::boolalpha << noexcept(foo()) << ' ' << noexcept(bar())
        << ' ' << noexcept(foo2()) << ' ' << noexcept(bar2()) << std::endl;    
}

Demo

所以看起来noexcept 的行为至少对于这两个编译器来说并不依赖于编译器选项。

更新:VS2013 doesn't support noexcept at all.

【讨论】:

    【解决方案2】:

    -fnothrow-opt 将 throw() 异常规范视为 noexcept 规范,以减少或消除文本大小开销 相对于没有异常规范的函数。如果 函数具有具有非平凡析构函数的类型的局部变量, 异常规范实际上使函数更小 因为这些变量的 EH 清理可以被优化掉。这 语义效果是函数抛出异常 这样的异常规范导致调用终止而不是 出乎意料。

    所以根据 gcc 文档,throw 函数变成了 noexcept 规范。

    这应该意味着更多的对象将返回 true 而不是更少

    【讨论】:

    • 这是与 OP 所要求的不同选项的文档。通过-fexceptions / -fno-exceptions 启用或禁用异常支持。
    猜你喜欢
    • 1970-01-01
    • 2017-03-12
    • 1970-01-01
    • 2011-10-17
    • 2023-03-11
    • 2012-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多