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>();
}
它应该编译吗?
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>();
}
它应该编译吗?
Foo_t<T>::Bar
看起来像是一个依赖名称,但实际上不是,因为在确定Bar
所引用的限定符id时,传递给别名声明的模板参数并没有被使用。
代码是合法的。
14.5.7/2 别名模板
[temp.alias]
当模板id引用别名模板的特化时,它等同于通过将其模板参数替换为别名模板的类型id而获得的相关类型。
A.6 Declarations
[gram.dcl]
alias-declaration: using identifier attribute-specifier-seq_opt = type-id ;
由于Foo_t
的type-id中没有template-parameters,所以无论我们传递什么template-arguments,template 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`
}
Foo_t <T>
是一个简单模板标识符,而其中的一个模板参数,即T
,是一个相关类型(dependent type)。 - T.C.Foo
。 Foo
显然不是一个依赖类型。这本身似乎是个矛盾。是否有明确的条款说明必须以不是依赖类型为基础解决这个矛盾?或者“等效”意味着什么?还是在[temp.dep.type] / p8中有一些子条款规定“这里不适用”? - Yakk - Adam Nevraumont经过进一步的调查,这是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
。在某些方面,别名模板的特化就像当前实例化一样,在模板定义时可以知道。
这个问题仍然处于“起草”状态,但看起来编译器供应商已经在实施预期的解决方案了。
template <class T> void f() { Foo::Bar b; }
,且不存在依赖名称。 - Kerrek SB