函数声明必须可用,因为没有任何参数依赖于模板参数

αλε*_*λυτ 8 c++ templates language-lawyer

以下代码在 trunk gcc 和 clang 中编译良好,但在 msvc for c++20 模式下编译失败:

template <typename T = int>
void f(void* ptr, T&& t = {}) {
    if (ptr) {
        f(nullptr);
    }
}
Run Code Online (Sandbox Code Playgroud)

与消息:

error C2672: 'f': no matching overloaded function found
note: could be 'void f(void *,T &&)'
note: 'void f(void *,T &&)': could not deduce template argument for 'T'
note: 'f': function declaration must be available as none of the arguments depend on a template parameter
Run Code Online (Sandbox Code Playgroud)

适用于 c++17 模式的 msvc,因为/permissive-自 c++20 以来仅默认可用。

f<T>(nullptr);对于 msvc c++20,可以通过显式指定模板类型(即在函数体中)轻松修复。

按照标准,谁是对的?我对 c++17 和 c++20 模式都感兴趣。即将推出的 c++23 是否会有任何变化?

use*_*570 4

这是CWG 2608,该程序格式良好,并且 gcc 和 clang符合标准

如果所有模板参数都可以从默认模板参数中推导或获得,则可以全部省略;在这种情况下,空模板参数列表 <> 本身也可以被省略。

(强调我的)

这意味着f(nullptr);是格式良好的,因为模板参数 forT可以从默认模板参数获得,因此它可以被省略,这意味着空模板参数列表 <> 本身也可以被省略。因此,gcc 和 clang 是符合标准的。另请注意,msvc 对此进行编译/permissive,因此没有理由提交错误报告,因为他们通常建议/permissive在提交错误之前使用标志。


您还可以通过添加空来确认这一点<>,然后您会注意到 msvc 会编译该程序。演示

template <typename T = int>
void f(void* ptr, T&& t = {}) {
    if (ptr) {
//-------vv-------------->msvc compiles this with empty <> - See CWG 2608
        f<>(nullptr);
    }
}

Run Code Online (Sandbox Code Playgroud)