函数对象上使用的 noexcept 运算符总是产生 true

noexcept operator used on function object always yields true

我 运行 无意中进入了这个,同时在尝试实现我自己的 std::visit 版本以用于教育目的时玩弄 noexcept 运算符。这是只有相关部分的代码:

#include <iostream>

template<typename... Ts>
struct visitor : Ts... { using Ts::operator()...; };
template<typename... Ts>
visitor(Ts...) -> visitor<Ts...>;

int main() {
    auto vis1 = visitor {
        [](int s) {
        },
        [](double s) {
        }
    };

    constexpr auto isNoExcept = noexcept(vis1);
    std::cout << std::boolalpha << isNoExcept << '\n';

    return 0;
}

这总是为我输出 true(gcc 和 clang)。

我有两个问题:

  1. 当有多个 operator() 时,如何应用 noexcept 运算符,因为有些可能是 noexcept,而其他则不是?怎么可能只有一个答案呢?这里到底发生了什么?
  2. 为什么 return true,即使 none 的 lambda 被声明为 noexcept

noexcept(vis1) 中,您要检查的表达式是 vis1。这个表达式的计算不可能抛出异常,因为它什么都不做。所以这个 returns true 不管 vis1.

定义的重载集中任何函数的异常规范

但是,如果您编写 noexcept(vis1(42)),则您正在检查计算表达式 vis1(42) 是否会引发异常。由于取int的重载没有标记noexcept,求值确实可能抛出异常,而这个returnsfalse.


为了回答您的具体问题,

How can the noexcept operator even be applied when there are multiple operator()s?

您不应该一次对所有 operator() 应用 noexcept 运算符,而应该一次只对一个特定的 operator() 应用,如我上面所示,并且在在这种情况下,编译器只检查将要选择的重载是否标记为 noexcept