5

Consider this example of a class template containing a member function and a member function template both of which are named f followed by an attempt to define and specialize the member function template:

template<typename T>
struct A {
    void f();
    template<typename U>
    void f();
};

template<>
template<typename U>
void A<double>::f() { }

template<>
template<>
void A<double>::f<int>() { }

Is this legal? How should the member function template definition be written?

In the first definition of f, does the template declaration ensure that the member function template f should be selected rather than the member function f even though the template parameter does not appear in the type? I don't see any way to further disambiguate this as writing ::template f(), ::f<U>(), ::f<>(), or a combination thereof does not seem to help.

Compiler results:

  • clang: crashes with a stack trace at the specialization of f<int>
  • Visual Studio: compiles successfully
  • gcc: compile error (ambiguity regarding which f is being defined) at the first definition of f
  • EDG: compiles successfully

By contrast, every compiler accepts the equivalent at namespace scope:

namespace X {
    void f();
    template<typename T>
    void f();
}
template<typename T>
void X::f() { }
template<>
void X::f<int>() { }
0x5f3759df
  • 2,349
  • 1
  • 20
  • 25

1 Answers1

2

This is a language defect report DR 1665, which is in drafting status at this moment.

As mentioned there the standard says

A normal (non-template) member function with a given name and type and a member function template of the same name, which could be used to generate a specialization of the same type, can both be declared in a class. When both exist, a use of that name and type refers to the non-template member unless an explicit template argument list is supplied.

And there is an open GCC bug report with an example very similar to yours: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64063

Fedor
  • 17,146
  • 13
  • 40
  • 131