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

Jac*_*ood 7 c++ templates noexcept c++17

我注意到 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 { };

Run Code Online (Sandbox Code Playgroud)

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

演示

Bri*_*ian 4

无法从noexcept-specifier推导出非类型模板参数。

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

例如,该条目T (T::*)(T)暗示如果形参类型和实参类型都是指向成员函数的指针,则可以从返回类型、类类型和任何实参类型(对于成员函数)推导出模板形参,如果它们出现在那里。

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

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

编辑(2022 年 10 月 20 日):看来这将在 C++23 中发生变化:i将从noexcept(i). 根据问题列表,它具有“DR”状态,这意味着它具有追溯性(大概是对 C++17)。

  • 同意。这会很好,并且与 [P0012R1](https://wg21.link/P0012R1) _“使异常规范成为类型系统的一部分”_ 配合得很好,它已经是 C++17 的一部分。 (2认同)