C++17函数noexcept说明符作非类型参数的MSVC推导问题
MSVC对带noexcept说明符的成员函数指针模板参数推导失败问题说明
- 该现象属于MSVC的编译器实现缺陷,相关代码完全符合C++17及后续版本的标准规范。
C++17标准明确规定,
noexcept说明符是函数类型的组成部分,函数类型中带模板形参的noexcept(IsNoexcept)属于合法的模板推导上下文,编译器应当能正确推导出对应的非类型模板实参。
测试代码
template <typename T> struct is_nocv_method : public std::false_type { }; template <typename ReturnT, typename ClassT, bool IsNoexcept, typename... Args> struct is_nocv_method<ReturnT (ClassT::*)(Args...) noexcept(IsNoexcept)> : std::true_type { };
实际编译表现
- GCC 12.1、Clang 14.0等遵循标准的编译器均可无错编译上述代码,正确完成
IsNoexcept参数的推导,匹配对应偏特化版本。 - MSVC 14.31(cl.exe版本19.31)及部分更早版本的模板推导逻辑存在遗漏,未将成员函数指针的
noexcept(非类型形参)形式纳入可推导上下文,因此抛出无法推导IsNoexcept的错误。
临时兼容方案
在MSVC推送修复前,可通过编写两个分别对应noexcept和noexcept(false)的偏特化版本绕开该缺陷:
// 匹配noexcept(true)的成员函数指针 template <typename ReturnT, typename ClassT, typename... Args> struct is_nocv_method<ReturnT (ClassT::*)(Args...) noexcept> : std::true_type { }; // 匹配noexcept(false)的成员函数指针 template <typename ReturnT, typename ClassT, typename... Args> struct is_nocv_method<ReturnT (ClassT::*)(Args...) noexcept(false)> : std::true_type { };
- 该缺陷已被MSVC开发团队确认,修复已合入预览版本,会随后续正式版编译器发布。
内容的提问来源于stack exchange,提问作者Jack Harwood
相关产品推荐
相关产品推荐

