函数调用表达式是否与单个非类型模板参数参数类型相关?

时间:2014-12-31 11:04:20

标签: c++ templates language-lawyer dependent-type compiler-bug

在以下示例中,clang 3.6和gcc 5.0都需要typename

template<typename T>
struct B
{
    typedef int Type;
};

void f(int);

template<int n>
struct A
{
    typedef typename B<decltype(f(n))>::Type Type;
};

C ++ 11标准中的以下措辞涵盖了这一点:

  

[temp.dep.type] / 5

     

名称是未知专业化的成员,如果它是

     
      
  • 一个qualified-id,其中嵌套名称说明符命名一个非当前的依赖类型   实例
  •   
     

[temp.dep.type] / 8

     

如果类型是

,则类型是依赖的      
      
  • 未知专业化的成员,

  •   
  • 一个simple-template-id,其中模板名称是模板参数或任何模板   arguments是依赖类型或依赖于类型或依赖于值的表达式

  •   
  • decltype(expression)表示,其中表达式依赖于类型

  •   

这表明B<decltype(f(n))>::Type仅在B<decltype(f(n))>与类型相关时才依赖于类型。此外,B<decltype(f(n))>仅在f(n)与类型相关时才依赖。

  

[temp.dep.expr] / 1

     

除非如下所述,否则如果任何子表达式依赖于类型,则表达式依赖于类型。

     

[temp.dep.expr] / 3

     

如果id-expression包含

,则它依赖于类型      
      
  • 通过名称查找关联的标识符,其中一个或多个声明使用依赖类型声明,

  •   
  • 依赖的模板ID,

  •   
  • 指定依赖类型的conversion-function-id,或

  •   
  • 用于命名未知专业化成员的嵌套名称说明符或qualified-id;

  •   
     

或者如果它命名当前实例化的静态数据成员,该实例的类型为“未知绑定的数组”   T“对于某些T

这表明,只有f(n)依赖于类型且n 类型相关时,n才是类型相关的。

我错过了什么,或者这是编译错误?

1 个答案:

答案 0 :(得分:2)

您的分析有点不完整,但正确无误。

  

qualified-id 旨在引用不是a的类型时   当前实例化的成员(14.6.2.1)及其成员    nested-name-specifier 是指依赖类型,它应以关键字typename作为前缀,形成 typename-specifier

显然B<…>::Type不能引用当前实例化的成员。所以问题是B<decltype(f(n))>是否是依赖类型。

  

如果类型是

,则类型是依赖的      
      
  • [...]
  •   
  • 未知专业的成员,
  •   
  • [...]
  •   
  • 一个 simple-template-id ,其中模板名称是模板参数或任何模板参数是依赖项   类型或类型相关或依赖于值的表达式,或
  •   
  • decltype(expression)表示,其中表达式与类型有关(14.6.2.2)。
  •   

f(n)不依赖于类型,因为没有子表达式,因此decltype(f(n))不是依赖类型。
此外,decltype(...)不能依赖于值,因为它不是常量表达式 1 ,并且[temp.dep.constexpr]中没有其他段落适用。显然,decltype(f(n))也不依赖于类型 只有当模板参数是依赖类型 2 时,B<decltype(f(n))>::Type才会成为未知专业化的成员,我们认为它不是

因此,根据我的解释,编译器不正确,并且不需要typename关键字。


1 事实上,decltype(…)根本不是表达。

2 [temp.dep.type] / 5:

  

如果名称是

,则该名称是未知专业化的成员      
      
  • qualified-id ,其中 nested-name-specifier 命名的依赖类型不是当前的实例化。
  •   
  • qualified-id ,其中嵌套名称说明符引用当前实例化,当前实例化至少有一个   依赖基类 qualified-id 的名称查找不会   找到当前实例化的类的任何成员或者   非依赖基类。
  •   
  • id-expression 表示类成员访问表达式(5.2.5)中的成员,其中任何一个   
        
    • [...]
    •   
  •