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

Viewed 869

A coworker shared this code with me:

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 prints 1, Clang prints 2, and MSVC complains about missing template arguments.

Which compiler is correct?

2 Answers

[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 authored by @DavisHerring.)

There is even an example almost identical to yours under it, identifying your use of template as ill-formed.

The requirement and example comes from CWG defect report 96, in which the possible ambiguity without the requirement is considered.

Open GCC bug report for this is 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 however does list the defect report as unimplemented.

MSVC is correct to reject this: the standard has just this as an example. The template parser guide is allowed before the qualified name of a class or alias template without template arguments, but this is only for compatibility with implementations that needlessly require it for template template arguments and is now deprecated.

Related