C++17中模板类实例可省参数列表,访问成员类型为何不行?
为什么C++17中
foo::type不支持但foo f1;可以? 首先得明确两个场景的本质区别:
foo f1;是创建类模板的实例对象,这用到了C++17新增的**类模板实参推导(CTAD)**机制。当你省略模板参数列表时,编译器会尝试根据上下文推导模板参数,这里因为模板有默认参数T=int,所以编译器自动用默认参数实例化出foo<int>,进而创建对象。- 而
foo::type是直接访问模板的成员类型,此时foo还只是一个模板的名字,不是一个具体的类类型。C++规则要求,只有当模板被实例化为具体类型后(哪怕是用<>触发默认参数,比如foo<>等价于foo<int>),你才能访问它的成员。直接写foo::type时,编译器不知道你要把foo实例化成哪个版本(哪怕有默认参数,规则也没允许在这种场景下自动用默认参数实例化),所以会编译失败。
简单总结:
- 创建对象时,CTAD允许编译器帮你补全模板参数(包括使用默认参数);
- 访问模板成员时,必须明确给出实例化后的类型(用
<>触发默认参数也算明确指定),不能让编译器自动推导。
对应的代码验证:
template<typename T = int> struct foo { using type = T; }; int main() { foo f1; // 合法:CTAD推导为foo<int> foo<>::type t2; // 合法:明确实例化为foo<int>,再访问成员type // foo::type t1; // 非法:foo是模板名,未实例化,无法访问成员 }
内容的提问来源于stack exchange,提问作者Jaan
相关产品推荐
相关产品推荐

