为什么 MSVC 不会抱怨 i 是 int 的表达式 i.str() ?

Jac*_*son 7 c++ windows winapi visual-c++

我得到了一些格式不正确的代码,如下所示,但它是使用 MSVC 19.32.31329 和 /std:c++latest 构建的。

#include <Windows.h>

template<typename T>
void foo() {
    int i;
    // Can be anything that looks like a function call
    baz(i.str());
}

int WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
    int i;
    // The following line is wrong because i has an integral type
    // and doesn't have .str().
    i.str();
}
Run Code Online (Sandbox Code Playgroud)

该代码显然是错误的,不应该编译,但它确实可以编译。这是编译器错误吗?

IIn*_*ble 7

是的,这是一个编译器错误,显然是在 19.32 版本中引入的。/std:c++latest使用或进行编译时可以观察到这一点/std:c++20

看来函数模板内的任何内容都可以诱骗 MSVC 学习有关整数类型的新规则。正如问题中所示,一旦编译器完成解析,foo它随后将允许任何exp整数类型的表达式调用任何(幻想)成员(例如str())(使用整数、浮点值、布尔值、指针和数组进行验证)。


在对该问题的评论中提出了一个相关问题。

当函数模板在这里foo 实例化时,MSVC将编译以下代码:

extern void bar(int);

template<typename T>
void foo()
{
    int i;
    // This should not compile
    bar(i.str());
}

int WinMain(void*, void*, char*, int)
{
    foo<int>();
}
Run Code Online (Sandbox Code Playgroud)

尽管这可能遵循法律条文中的规则[temp.res.general/6.4] :

如果出现以下情况,则程序格式错误,无需诊断:

  • ...
  • 由于不依赖于模板参数的构造,紧随其定义之后的模板的假设实例化将是格式错误的,或者

确实,改成int i无法auto i = sizeof(T) 编译。这可能是无关的。


错误报告已发布(请参阅此答案)。


use*_*570 2

这是一个 msvc 错误。该程序格式错误,无需诊断这可以从temp#res.general6.1中看出,其中指出:

  1. 可以在任何实例化之前检查模板的有效性。

如果出现以下情况,则程序格式错误,无需诊断

  • 6.1) 无法为模板或模板内 constexpr if 语句的子语句生成有效的特化,并且模板未实例化,或者

此外,temp#res.general6.4也适用于此处:

由于不依赖于模板参数的构造,紧随其定义之后的模板的假设实例化将是格式错误的,或者

(强调我的)


相同的错误报告已提交为:

someint.str()当存在无效的函数模板时,调用将编译