基类中类型为依赖子类模板参数数组的成员变量不可访问原因
问题:模板继承中成员变量可见性的差异原因
以下代码无法编译:
template <class T> struct Base { T m_data; }; template <int size> struct Sub : public Base<int[size]> { int f() { return m_data[0]; } };
在clang和gcc编译器中,f()的函数体都会报错:use of undeclared identifier 'm_data'。
有两种修改方式可以让代码正常编译:
- 将
int[size]替换为int[7],代码可正常编译(但不符合使用模板参数size的实际需求); - 将
return m_data[0]替换为return Base<int[size]>::m_data[0],代码也可编译,这解决了实际问题。
核心疑问:为什么使用int[size]时m_data在Sub中不可见,而int[7]却可以?
原因分析
这本质是C++模板的名称查找规则导致的差异:
- 当基类依赖于模板参数时(这里
Base<int[size]>中的size是Sub的模板参数,属于「依赖型基类」),编译器在模板定义阶段(还未拿到具体模板参数值时)不会解析基类的成员名称。因为此时基类的具体类型尚未确定,编译器无法提前确认m_data是否存在,因此直接报未声明错误。 - 当把模板参数替换为固定值
7后,Base<int[7]>变成了非依赖型基类——它的类型在模板定义阶段就是确定的。编译器可以直接解析这个基类的成员,自然能找到m_data,代码也就可以正常编译。
而显式添加Base<int[size]>::限定作用域后,相当于告诉编译器:m_data是来自这个依赖型基类的成员,需要延迟到模板实例化阶段(此时size已有具体值,基类类型完全确定)再去查找,这样就能正确定位到m_data了。
内容的提问来源于stack exchange,提问作者Sven Sandberg
相关产品推荐
相关产品推荐

