存在同名成员函数时,成员函数模板的类定义外 - 编译器分歧

0x5*_*9df 5 c++ templates overloading ambiguous language-lawyer

考虑这个包含成员函数和成员函数模板的类模板的示例,这两个模板都被命名,f然后尝试定义和专门化成员函数模板:

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>() { }
Run Code Online (Sandbox Code Playgroud)

这合法吗?成员函数模板定义应该怎么写?

在 的第一个定义中f,模板声明是否确保即使模板参数没有出现在类型中,也f应选择成员函数模板而不是成员函数?f我没有看到任何方法可以进一步消除歧义,因为编写::template f()::f<U>()::f<>()或它们的组合似乎没有帮助。

编译结果:

  • clang:在专业化时因堆栈跟踪而崩溃f<int>
  • Visual Studio:编译成功
  • fgcc:在第一个定义处出现编译错误(正在定义的内容不明确)f
  • EDG:编译成功

相比之下,每个编译器都接受命名空间范围内的等效内容:

namespace X {
    void f();
    template<typename T>
    void f();
}
template<typename T>
void X::f() { }
template<>
void X::f<int>() { }
Run Code Online (Sandbox Code Playgroud)

Fed*_*dor 2

这是一份语言缺陷报告DR 1665 ,目前处于起草状态。

正如那里提到的,标准说

具有给定名称和类型的普通(非模板)成员函数以及可用于生成相同类型的特化的同名成员函数模板都可以在类中声明。当两者都存在时,除非提供显式模板参数列表,否则该名称和类型的使用将引用非模板成员。

还有一个开放的 GCC 错误报告,其中的示例与您的非常相似:https://gcc.gnu.org/bugzilla/show_bug.cgi ?id=64063