带noexcept的函数指针重载决议:编译器行为差异及正确性判定
C++ noexcept函数的重载决议标准行为分析
初始重载函数
template<class T_ret, class... Args> int test(T_ret (*func)(Args...)) { return 1; } template<typename T> int test(const T &lambda) { return 2; }
问题场景
当传递带有noexcept说明符的函数时,不同编译器的重载决议结果存在差异:
示例代码:
void func() noexcept {} int main() { return test(&func); }
- GCC与Clang会选择第二个重载(返回2)
- MSVC会选择第一个重载(返回1)
添加带有noexcept说明符的更特化重载后,所有编译器都会选择该重载:
template<class T_ret, class... Args> int test(T_ret (*func)(Args...) noexcept) { return 3; }
标准合规性分析
根据C++标准,noexcept是函数类型的一部分——void() noexcept和void()属于不同的函数类型。
对于第一个重载模板,其参数是不带noexcept限定的函数指针类型,而&func的实际类型是void(*)() noexcept。由于两种函数指针类型不匹配,模板推导会失败,因此编译器不能选择第一个重载。此时第二个模板会被匹配:T被推导为void(*)() noexcept,因此选择第二个重载是符合标准的正确行为。
而添加第三个重载后,其参数类型与&func完全匹配,模板推导成功,因此所有编译器都会优先选择这个最匹配的重载。
内容的提问来源于stack exchange,提问作者maxbachmann
相关产品推荐
相关产品推荐

