【问题标题】:Hiding of member function templates - Which compiler is correct?隐藏成员函数模板 - 哪个编译器是正确的?
【发布时间】:2018-03-27 21:41:19
【问题描述】:

我写了以下隐藏成员函数模板的代码。

#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>();

那么,哪个编译器是正确的?

【问题讨论】:

  • 另外,既然你有using A::func,你根本没有做任何隐藏。相反,您可以在 B 类中完整查看 both 模板函数。
  • 最后,您忘记将代码保存在 rextester 上。您现在拥有的链接是每个编译器的通用链接。
  • 有趣。我试图在这方面查找标准。但它仅指定应在模板参数上进行隐式转换以使其适合参数。没有关于对转化进行排名的问题。很有意思。如果还没有缺陷报告(或者我错过了标准草案中的某些内容),则可以作为缺陷报告的基础。
  • @MarekR 不,这就是您将编译时常量作为模板参数传递给模板的方式。
  • this尤其是T.C.的评论值得一读

标签: c++ c++11 templates gcc clang


【解决方案1】:

关于 OP 中的示例:正如 W.F. 向我指出的那样,这里重要的是那些是 member 功能模板。您添加了一个 using 声明,它指定 ([namespace.udecl]/15):

当使用声明将名称从基类带入派生类时 类范围、成员函数和成员函数模板 派生类覆盖和/或隐藏成员函数和成员 基础中具有相同名称、参数类型列表、cv 限定符和 ref 限定符(如果有)的函数模板 类(而不是冲突)。

请注意如何计算模板参数。而正是 Clang 通过隐藏 int 版本正确处理了代码。


另一方面,如果检查tobi303 建议的under your post 示例,GCC 是正确的。这根本没有指定以某种方式解决。

其中一个是[temp.fct.spec]/3

可以推导出的尾随模板参数或 从默认模板参数获得的可以从列表中省略 显式模板参数。 [...] 在扣除的情况下 完成和失败,或在未完成扣除的情况下,如果 指定模板参数列表,并且它以及任何默认值 模板参数,标识单个函数模板 特化,则模板 ID 是函数的左值 模板专业化

粗体字表示你的程序只有当我们给出的模板参数指定一个特化时才是格式正确的。从表面上看,它没有,因为根据[temp.arg.nontype]/1

非类型、非模板模板参数的模板参数 应为以下之一:

  • 对于整数或枚举类型的非类型模板参数,转换后的类型的常量表达式 模板参数;

并且 0 适合作为转换后的常量表达式的两个重载。由于模板参数没有任何 ICS 排名,因此这是模棱两可的。

【讨论】:

  • 理论上还有一件事需要考虑 - 如果不能忽略 using 本身,因为类中存在此名称的重载...
  • @W.F. - 我不确定我是否跟随。如何忽略 using 声明?
  • 抱歉我的措辞选择不当 :) 我的意思是this
  • example compiles since gcc 7.1,所以 gcc 是对的。
猜你喜欢
  • 1970-01-01
  • 2017-05-09
  • 1970-01-01
  • 1970-01-01
  • 2013-03-31
  • 1970-01-01
  • 2018-11-09
  • 1970-01-01
  • 2013-01-26
相关资源
最近更新 更多