函数对象上使用的 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)。
我有两个问题:
- 当有多个
operator()
时,如何应用 noexcept
运算符,因为有些可能是 noexcept
,而其他则不是?怎么可能只有一个答案呢?这里到底发生了什么?
- 为什么 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
。
我 运行 无意中进入了这个,同时在尝试实现我自己的 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)。
我有两个问题:
- 当有多个
operator()
时,如何应用noexcept
运算符,因为有些可能是noexcept
,而其他则不是?怎么可能只有一个答案呢?这里到底发生了什么? - 为什么 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 multipleoperator()
s?
您不应该一次对所有 operator()
应用 noexcept
运算符,而应该一次只对一个特定的 operator()
应用,如我上面所示,并且在在这种情况下,编译器只检查将要选择的重载是否标记为 noexcept
。