是`使用Base :: operator T`允许`T`是模板类型参数?

时间:2016-07-27 09:15:00

标签: c++ templates conversion-operator using-declaration

考虑这个例子:

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;
};

2 个答案:

答案 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;
}