'类型名'和别名模板

时间:2015-03-10 15:35:30

标签: c++ templates c++11 language-lawyer

以下代码编译using both Clang and GCC,即使Foo_t<T>::Bar前面没有typename

struct Foo {
    using Bar = int;
};

template<class...>
using Foo_t = Foo;

template<class T>
void f(){
    Foo_t<T>::Bar b; // No typename!
}

int main(){
    f<int>();
}

它应该编译吗?

2 个答案:

答案 0 :(得分:16)

简介

Foo_t<T>::Bar可能看起来像一个依赖名称,但它不是因为传递给 alias-declaration template-arguments 不会被使用确定 qualified-id Bar所指的内容。

代码格式正确。



标准(N3337)说什么?

  

14.5.7 / 2 别名模板 [temp.alias]

     
    

template-id 引用别名模板的特化时,它等同于关联的类型     通过将 template-arguments 替换为别名的 type-id 中的 template-parameters 获得     模板。

  

  

A.6 声明 [gram.dcl]

     
alias-declaration:
  using identifier attribute-specifier-seq_opt = type-id ;


什么是标准真的说什么?

由于Foo_t type-id 中没有 template-parameters 模板alias-declaration 始终是直接等同于Foo,无论我们传递给它的 template-arguments

template<class... Ts>
using Foo_t = Foo;
//            ^--- "Foo" = type-id

Foo_t<T>的用法替换为模板alias-declaration 的等价物,为我们留下以下内容:

template<class T>
void f(){
    Foo::Bar b; // ok, nothing here depends on `T`
}

答案 1 :(得分:8)

进一步挖掘,这是CWG issue 1390

问题描述是

  

根据14.6.2.1 [temp.dep.type]第8段,类型是依赖的   (除其他外)如果是

     
    

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

  
     

这适用于别名模板特化,即使是结果   type不依赖于模板参数:

struct B { typedef int type; };
template<typename> using foo = B;
template<typename T> void f() {
  foo<T>::type * x;  //error: typename required
}
     

对此类案件的规则进行更改是否有必要?

这个问题有一个注释:

  

2012年10月会议的说明:

     

CWG同意在这种情况下不需要typename。在一些   方式,别名模板专业化就像当前一样   实例化,可以在模板定义时知道。

问题仍处于“起草”状态,但看起来编译器供应商已经在实施预期的解决方案。