为什么noexcept
运算符采用表达式而不是函数签名/声明?
考虑以下虚拟示例:
#include <string>
void strProcessor(const std::string& str) noexcept(true) { };
struct Type{
void method1() noexcept(strProcessor("")) { //Error: Call to nonconstexpr function
strProcessor("");
}
};
它不会编译,因为method1
在noexcept中有一个非constexpr表达式,但为什么我需要首先在其中放置一个表达式?
我想要做的就是告诉编译器 method1
是noexcept如果调用strProcessor
并且成功构造的字符串是noexcept (它是)。< / p>
那么为什么不noexcept(void strProcessor(const std::string&))
?
另一个类似的虚拟例子:
struct Type{
Type(bool shouldThrow=false) noexcept(false) { if(shouldThrow) throw "error"; };
void method1() noexcept(true) {};
void method2() noexcept(noexcept(Type().method1())) { method1(); };
}
这里我想说 method2
是nocept,如果在一个成功构造的Type的实例上调用method1
是noexcept (在这种情况下就是这样),但是在Type
id定义的位置,method2
甚至没有完成。
请解释我对此功能的理解是否错误。
答案 0 :(得分:9)
void method1() noexcept(noexcept(strProcessor(""))) {
// Second 'noexcept' ^^^^^^^^^ ^
第一个是noexcept
specifier,其中指定 method1()
是否 noexcept 。
嵌套的是noexcept
operator,当使用strProcessor()
调用时,检查 ""
是否 noexcept 。
你的第二个案例有点棘手:Type
在我们想要method1()
内使用noexcept
时仍然不完整。我来到以下解决方法,滥用指向成员的指针:
void method2() noexcept(noexcept(
(std::declval<Type>().*&Type::method1)()
)) {};
但是,我不认为您只能从method2()
推断出method1()
的 noexcept 规范。
答案 1 :(得分:2)
如果在检查函数的noexcept
时需要一些语法糖,可以使用如下的辅助函数:
template <typename R, typename... Params>
constexpr bool is_noexcept(R(*p)(Params...)) {
return noexcept(p(std::declval<Params>()...));
}
然后适用:
void method1() noexcept(is_noexcept(strProcessor)) …