【问题标题】:Is `using Base::operator T` allowed where `T` is a template type parameter?在“T”是模板类型参数的情况下,是否允许“使用 Base::operator T”?
【发布时间】:2016-12-01 05:05: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;
};

【问题讨论】:

  • 如果您在B 中将operator int() 设为模板化转换函数(例如template &lt;typename T&gt; operator T();),则它可以工作,如果您将其专门用于int,它也可以工作并调用专业化,而作为据我了解,标准禁止它(“由于名称查找未找到转换函数的成员模板的特化,因此在 using-declaration 指定转换函数时不考虑它们(14.5.2)。”)。另外,如果你在成员函数中调用,clang 可以找到operator T,所以我认为 gcc 是对的。

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


【解决方案1】:

嗯... Gcc 也不喜欢第一个。除非您尝试使用除int 之外的模板参数创建struct X 的实例,否则它将编译。 X&lt;double&gt;::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;
}

【讨论】:

  • 这并不意味着 GCC 是错误的。如果您将转换运算符模板化为B,并将其专门用于int,所有编译器都会很高兴,但您的程序不会为int以外的任何其他类型编译(链接失败)(使用任何编译器)。
  • @101010 这正是我所写的:除非您尝试使用int 以外的模板参数创建结构 X 的实例,否则它会编译。
  • @Holt 我从来没有说过 GCC 是错误的。我知道,模板化运算符有效。但问题是:为什么 B 中的模板化运算符有效,而 B 中的运算符 int() 适用于 GCC 而不适用于 MSVC 和 clang? 我相信我已经回答了这个问题。此外,如果我从我的答案中获取代码并将 X 更改为 X 它仍然无法编译 im MSVC,但它开始在 GCC 中编译。
  • @Lehu 很抱歉这种谜语的评论。我的意思是您没有回答 OP 关于哪个编译器表现出标准行为的问题。
  • @Lehu 由于格式错误的代码(带有X &lt;char&gt;的gcc)而无法实例化模板的编译器与“定义”模板(clang)时失败的编译器之间存在差异. OP 询问标准是否为给定代码指定了以前或以后的行为。
【解决方案2】:

我认为 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不是成员函数模板的特化,所以上面不应该考虑。

【讨论】:

    猜你喜欢
    • 2012-02-03
    • 1970-01-01
    • 2019-09-10
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 2018-02-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多