12

考虑这个例子:

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

2 回答 2

3

我认为 GCC 是对的,在 §7.3.3/1 中,我们可以找到:

通过对 using-declaration 中的名称执行限定名称查找 (3.4.3, 10.2) 可以找到由 using-declaration 引入的声明集,不包括如下所述的隐藏函数。

实际上,我看不出有什么理由operator T找不到:

template<class T>
struct X: B {
    T f () { return B::operator T; }
};

...用 g++ 和 clang 编译得很好(没有在 MSVC 上测试)。

我在特定于用于限定名称查找的转换函数的标准中找不到任何内容,除了:

由于不能通过名称查找找到转换函数的成员模板的特化,因此当 using 声明指定转换函数 (14.5.2) 时不考虑它们。

但是B::operator int不是成员函数模板的特化,所以上面不应该考虑。

于 2016-07-27T10:04:35.577 回答
-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;
}
于 2016-07-27T09:58:21.527 回答