隐藏成员函数模板 - 哪个编译器是正确的?

时间:2017-10-16 11:20:11

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

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

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

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

1 个答案:

答案 0 :(得分:12)

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

  

当using声明将基类中的名称带入派生类时   类范围,成员函数和成员函数模板   派生类覆盖和/或隐藏成员函数和成员   基础中具有相同名称,参数类型列表,cv-qualification和ref-qualifier(如果有)的函数模板   上课(而不是冲突)。

请注意不考虑模板参数。 Clang通过隐藏int版本来正确处理代码。

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

首先,有[temp.fct.spec]/3

  

可以推断的尾随模板参数或   从列表中可以省略从默认模板参数获得的参数   显式模板参数。 [...] 在演绎的情况下   完成和失败,或者在没有进行演绎的情况下,如果a   指定模板参数列表,以及任何默认值   模板参数,标识单个函数模板   特化,然后template-id是函数的左值   模板专业化

粗体文本表示只有我们提供的模板参数指定一个特化时,您的程序才是格式良好的。表面上看,它没有,因为根据[temp.arg.nontype]/1

  

非类型非模板模板参数的模板参数   应该是以下之一:

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

0适合两个重载作为转换常量表达式。由于模板参数没有任何ICS排名,这是不明确的。