T.C*_*.C. 24 c++ templates language-lawyer c++11
以下代码使用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>();
}
Run Code Online (Sandbox Code Playgroud)
它应该编译吗?
Fil*_*efp 16
Foo_t<T>::Bar可能看起来像一个依赖名称,但它不是因为在确定qualified-id引用的内容时不使用传递给alias-declaration的template-arguments. Bar
代码格式正确.
14.5.7/2 别名模板
[temp.alias]当模板id是指一个别名模板的专业化,它相当于通过其置换得到的相关联的类型的模板的参数为模板参数在类型ID别名模板.
A.6 声明
[gram.dcl]Run Code Online (Sandbox Code Playgroud)alias-declaration: using identifier attribute-specifier-seq_opt = type-id ;
由于没有模板参数的类型ID的Foo_t,该模板别名声明总是直接等同于Foo,无论什么模板参数,我们传递给它.
template<class... Ts>
using Foo_t = Foo;
// ^--- "Foo" = type-id
Run Code Online (Sandbox Code Playgroud)
Foo_t<T>用模板别名声明的等价替换用法使我们得到以下内容:
template<class T>
void f(){
Foo::Bar b; // ok, nothing here depends on `T`
}
Run Code Online (Sandbox Code Playgroud)
通过更多挖掘,这是CWG问题1390.
问题描述是
根据14.6.2.1 [temp.dep.type]第8段,如果是,则类型依赖于(除其他外)
一个simple-template-id,其中模板名称是模板参数或任何模板参数是依赖类型或依赖于类型或依赖于值的表达式
这适用于别名模板特化,即使结果类型不依赖于模板参数:
Run Code Online (Sandbox Code Playgroud)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在这种情况下不应该要求.在某些方面,别名模板特化与当前实例化类似,可以在模板定义时知道.
该问题仍然处于"起草"状态,但看起来编译器供应商已经在实现预期的解决方案.