'typename'和别名模板
'typename' and alias templates
以下代码同时使用 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>();
}
它应该编译吗?
简介
Foo_t<T>::Bar
可能看起来像一个依赖名称,但事实并非如此,因为在确定限定 id Bar
引用的内容时,不会使用传递给别名声明的模板参数。
代码格式正确。
标准 (N3337) 怎么说?
14.5.7/2 别名模板
[temp.alias]
当模板 id 引用别名模板的专用化时,它等效于关联的类型 通过将其模板参数替换为别名的类型 ID 中的模板参数获得 模板。
A.6 声明
[gram.dcl]
alias-declaration: using identifier attribute-specifier-seq_opt = type-id ;
标准到底在说什么?
由于 Foo_t
的类型 id 中没有模板参数,模板别名声明总是直接等价于 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`
}
再深入挖掘一下,这就是CWG问题1390。
问题描述为
根据 14.6.2.1 [temp.dep.type] 第 8 段,类型从属 (除其他外)如果是
简单模板 ID,其中模板名称为模板 参数或任何模板参数是依赖类型或 与类型相关或值相关的表达式
这适用于别名模板专用化,即使生成的 类型不依赖于模板参数:
对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
。在一些 方式,别名模板专用化就像当前的 实例化,并且可以在模板定义时知道。
该问题仍处于"起草"状态,但看起来编译器供应商已经在实施预期的解决方案。
- 部分定义/别名模板模板参数
- 如何在C++20中创建模板别名的推导指南
- 告诉c++编译器该参数没有别名
- 为什么返回类型中需要typename?C++
- boost::spirit::karma 替代生成器,带有 boost::variant 由字符串和字符串别名组成
- 继承模板类中的类型别名
- 别名模板的专业化 C++11 中没有开销的最佳替代方案
- 为什么 GCC 在使用类型别名时处理 const reinterpret_cast不同?
- 类作用域的类型别名"using":[何时]方法中的用法可以先于类型别名?
- 为什么我们不能重复使用具有不同模板参数的别名模板标识符?
- C++模板/别名 - 模板参数列表中参数 1 处的类型/值不匹配
- 如何使用类型别名从模板化类中隐藏模板列表
- C++ assigment std::list:<typename>:itrator 在 main 中工作,但在方法中它不起作用
- 模板模板参数和模板别名:编译器错误?
- 使用 'typename' 关键字将非类型视为依赖上下文中的类型
- 使用定义函数模板别名
- 为模板参数包添加别名
- 如何检测类型类型别名?
- C++类型别名,其中值被替换
- 'typename'和别名模板