我编写了以下隐藏成员函数模板的代码。
#include <iostream>
struct A
{
template<int> void func()
{
std::cout<<"Function tamplate of A"<<std::endl;
}
};
struct B : A
{
template<char> void func()
{
std::cout<<"Function tamplate of B"<<std::endl;
}
using A::func;
};
int main()
{
B().func<0>();
}
此程序在 Clang 编译器中工作。 Live demo Clang
但是, GCC 编译器会出现歧义错误。Live demo GCC
source_file.cpp: In function ‘int main()’:
source_file.cpp:22:17: error: call of overloaded ‘func()’ is ambiguous
B().func<0>();
那么,哪个编译器是正确的?
答案 0 :(得分:12)
关于OP中的示例:正如W.F.所指出的那样,重要的是那些是成员功能模板。您添加了一个using声明,指定了([namespace.udecl]/15):
当using声明将基类中的名称带入派生类时 类范围,成员函数和成员函数模板 派生类覆盖和/或隐藏成员函数和成员 基础中具有相同名称,参数类型列表,cv-qualification和ref-qualifier(如果有)的函数模板 上课(而不是冲突)。
请注意不考虑模板参数。 Clang通过隐藏int
版本来正确处理代码。
另一方面,如果检查tobi303建议under your post的示例,GCC就是正确的。这根本没有指定以某种方式解决。
首先,有[temp.fct.spec]/3:
可以推断的尾随模板参数或 从列表中可以省略从默认模板参数获得的参数 显式模板参数。 [...] 在演绎的情况下 完成和失败,或者在没有进行演绎的情况下,如果a 指定模板参数列表,以及任何默认值 模板参数,标识单个函数模板 特化,然后template-id是函数的左值 模板专业化。
粗体文本表示只有我们提供的模板参数指定一个特化时,您的程序才是格式良好的。表面上看,它没有,因为根据[temp.arg.nontype]/1:
非类型非模板模板参数的模板参数 应该是以下之一:
- 表示整数或枚举类型的非类型模板参数,是转换后的常量表达式的类型 模板参数;
0适合两个重载作为转换常量表达式。由于模板参数没有任何ICS排名,这是不明确的。