alf*_*lfC 7 overloading overload-resolution noexcept c++11 c++17
我试图了解 noexcept 功能。我知道这可能会令人困惑,但除此之外,如果可能的话,不能从调用函数中推导出来。
这是这种情况的非工作示例,
void f(){}
void f() noexcept{} // not allowed in c++
void g(){f();} // should call f
void h() noexcept{f();} // should call f noexcept
int main(){
g();
h();
}
Run Code Online (Sandbox Code Playgroud)
如果调用函数 ( h) 中没有 try/catch 块,那么编译器可以推断出有人对调用特定的 f 感兴趣。
此模式是否以其他解决方法形式使用?
我所能想象的就是这样的东西,但它不是很通用:
template<bool NE> void F() noexcept(NE);
template<>
void F<true>() noexcept(true){}
template<>
void F<false>() noexcept(false){}
void g(){F<noexcept(g)>();} // calls F<false>
void h() noexcept{F<noexcept(h)>();} // call F<true>
Run Code Online (Sandbox Code Playgroud)
有些人可能想知道为什么这会有意义。我的逻辑是,C++ 允许重载const函数参数和成员函数。
const例如,成员函数更喜欢调用const成员重载。
我认为noexcept函数调用noexcept“重载”是有意义的。特别是如果它们不是从 try/catch 块中调用的。
当然,原则上这是有道理的。该函数的一个版本可以运行更快的算法,但需要动态分配额外的暂存内存,而 noexcept 版本可以使用较慢的算法,在堆栈上具有 O(1) 额外空间。
如您所知,noexcept(false)从noexcept(true)函数调用函数是完全有效的。你只是冒着抛出异常的风险terminate,而不是抛出异常;有时 - 您不会冒任何风险,因为您已经验证了您传递的输入不会触发异常。那么,编译器如何知道您正在调用哪个版本的函数呢?对于另一个方向也是同样的问题 - 也许您想noexcept(true)从noexcept(false)函数内调用您的函数?这也是允许的。
使用 C++11,您可以编写:
#include <stdexcept>
template <bool ne2>
int bar(int x) noexcept(ne2);
template<> int bar<true>(int) noexcept { return 0; }
template<> int bar<false>(int) { throw std::logic_error("error!"); }
Run Code Online (Sandbox Code Playgroud)
这编译得很好GodBolt:
因此,您可以拥有两个具有相同名称和相同参数的函数,仅在其noexcept值方面有所不同 - 但具有不同的模板参数。