C++17:将函数 noexcept 说明符推导为非类型参数

C++17: Deducing function noexcept specifier as non-type parameter

我注意到 MSVC 有时无法推断出其他编译器接受的非类型参数,并且最近遇到了一个涉及函数 noexcept 说明符(自 C++17 以来它是函数签名的一部分)的简单示例:

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 { };

Godbolt 建议 gcc 12.1 和 clang 14.0 毫无问题地接受它,但 MSVC 14.31 (cl.exe 19.31) 无法编译,声称无法推导出 IsNoexcept。这是编译器缺陷吗?

Demo

查看此错误报告:https://developercommunity.visualstudio.com/t/noexcept-is-not-deducible-in-partial-spe/841571

而这个问题,由 EWG 批准:https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1018r9.html#CWG2355

似乎从 noexcept 说明符中推导目前是非标准的,但这被认为是一种疏忽并且将被修复。

无法从 noexcept-specifier.

中推导出 non-type 模板参数

[temp.deduct.type]/8 给出了可以从中推导出模板参数的上下文列表。本质上,它可以理解为“解包”参数类型的方法列表,以及解包类型中可以从中推导出模板参数的位置列表。

例如T (T::*)(T)项表示如果参数类型和实参类型都是指向成员函数的指针,那么模板参数可以从return类型推导出来,class 类型和任何参数类型(对于成员函数),它们应该出现在那里。

您会注意到没有 T() noexcept(i)T(T) noexcept(i) 等形式的项目。

然而,一些编译器仍然选择允许这种推导,可能是因为它很方便。我支持将其添加到标准中。