'typename'和别名模板

24
以下代码可使用Clang和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>();
}

它应该编译吗?


6
模板别名在使用时会立即被替换,因此代码等同于 template <class T> void f() { Foo::Bar b; },且不存在依赖名称。 - Kerrek SB
2个回答

16

介绍

Foo_t<T>::Bar看起来像是一个依赖名称,但实际上不是,因为在确定Bar所引用的限定符id时,传递给别名声明模板参数并没有被使用。

代码是合法的。



标准(N3337)中的解释

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

模板id引用别名模板的特化时,它等同于通过将其模板参数替换为别名模板的类型id而获得的相关类型。

A.6 Declarations [gram.dcl]

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

标准究竟在说什么?

由于Foo_ttype-id中没有template-parameters,所以无论我们传递什么template-argumentstemplate alias-declaration始终直接等效于Foo

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

Foo_t<T>的使用替换为模板别名声明的等价物,会让我们得到以下内容:

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

那么 [temp.dep.type]/p8 - “如果一个类型是依赖型的,当它是一个simple-template-id并且其中任何模板参数是依赖型时…” 只适用于别名模板替换后的类型吗? - T.C.
@T.C. 别名声明中的 type-id 不是一个 simple-template-id - Filip Roséen - refp
1
不,我是在说Foo_t <T>是一个简单模板标识符,而其中的一个模板参数,即T,是一个相关类型(dependent type)。 - T.C.
3
@FilipRoséen-refp 也许是这样,但它同时也是一个简单的模板标识符,其中一个模板参数是一个依赖类型。因此,根据该条款,它是一个依赖类型。在别名模板条款下,它等效于FooFoo显然不是一个依赖类型。这本身似乎是个矛盾。是否有明确的条款说明必须以不是依赖类型为基础解决这个矛盾?或者“等效”意味着什么?还是在[temp.dep.type] / p8中有一些子条款规定“这里不适用”? - Yakk - Adam Nevraumont
@Yakk 我回到家后会回复并更新答案;相关措辞在标准中。(我用黑莓写的) - Filip Roséen - refp

9

经过进一步的调查,这是CWG问题1390

该问题的描述为:

According to 14.6.2.1 [temp.dep.type] paragraph 8, a type is dependent (among other things) if it is

a simple-template-id in which either the template name is a template parameter or any of the template arguments is a dependent type or an expression that is type-dependent or value-dependent

This applies to alias template specializations, even if the resulting type does not depend on the template argument:

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

Is a change to the rules for cases like this warranted?

这个问题有一个注释:

2012年10月会议记录:

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

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


据我所知,提到的编译器供应商一直按照所描述的方式实施,但他们的实现并反映那个DR的内容。老实说,我认为这个DR有点..嗯,“没有经过深思熟虑” - 标准中有必要的措辞来得出我在帖子中的结论。 - Filip Roséen - refp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接