考虑这个例子:
struct B { operator int(); };
template<class T>
struct X:B
{
using B::operator T;
};
GCC接受代码,而Clang和MSVC拒绝它。 哪个是对的?
请注意,如果基类型是相关的,则所有编译器都接受代码:
template<class T>
struct B { operator T(); };
template<class T>
struct X:B<T>
{
using B<T>::operator T;
};
答案 0 :(得分:3)
我认为GCC是对的,在§7.3.3/ 1中,我们可以找到:
using-declaration引入的声明集是通过对using-declaration中的名称执行限定名称查找(3.4.3,10.2)找到的,不包括如下所述隐藏的函数。
我看不出为什么找不到operator T
的原因,实际上:
template<class T>
struct X: B {
T f () { return B::operator T; }
};
...用g ++和clang编译好(没有在MSVC上测试)。
我无法在标准中找到任何特定于转换函数的标准名称查找,除了:
由于名称查找未找到转换函数的成员模板的特化,因此当using声明指定转换函数时不会考虑它们(14.5.2)。
但是B::operator int
不是成员函数模板的特化,所以上面不应该考虑它。
答案 1 :(得分:-1)
嗯...... Gcc也不喜欢第一个。除非您尝试使用除struct X
之外的模板参数创建int
的实例,否则它将进行编译。 X<double>::operator double()
的含义是什么? B类没有这样的运营商,但我们会尝试使用它。
总结一下:MSVC和clang会事先警告你(即使你现在没有做任何愚蠢的事情),而gcc只有在你试图创造不正确的东西时才会产生错误。这不能在gcc(5.3.0)中编译:
#include <iostream>
struct B { operator int(); };
template<class T>
struct X:B
{
using B::operator T;
};
int main(int argc, char **argv)
{
X<char> x;
std::cout << "Hello!" << std::endl;
return 0;
}