当同时存在模板和非模板重载时,`foo.template bar()` 应该做什么?

What should `foo.template bar()` do when there's both a template and a non-template overload?

一位同事与我分享了这段代码:

run on gcc.godbolt.org

#include <iostream>

struct A
{
    void foo() {std::cout << "1\n";}
    
    template <typename T = int>
    void foo() {std::cout << "2\n";}
};

int main()
{
    A x;
    x.template foo();
}

GCC 打印 1,Clang 打印 2,而 MSVC 抱怨缺少模板参数。

哪个编译器是正确的?

[temp.names]/5 says that a name prefixed by template must be a template-id, meaning that it must have a template argument list. (Or it can refer to a class/alias template without template argument list, but this is deprecated in the current draft as a result of P1787R6 由@DavisHerring 撰写。)

下面甚至还有一个与您几乎相同的示例,表明您对 template 的使用是错误的。

需求和示例来自CWG defect report 96,其中考虑了没有需求可能产生的歧义。

为此打开 GCC 错误报告 here. I was not able to find a Clang bug report, but searching for it isn't that easy. Its implementation status page for defect reports 但是确实将缺陷报告列为未实现。

MSVC 拒绝这个是正确的:标准就是 an exampletemplate 解析器指南 允许在 class 的限定名称或没有模板参数的别名模板之前,但这只是为了与不需要它的实现兼容用于模板模板参数,现已弃用。