C++模板继承中模板参数被隐藏,如何引用派生类模板参数T?
解决模板派生类中同名名称查找的优先级问题
先看你的代码问题:
template <typename> struct B { constexpr static int T = 5; }; template <int T> struct D : B<int> { constexpr static int value = T; }; int main() { std::cout << D<7>::value << std::endl; // 输出5,如何让它输出7? }
你对问题的判断完全正确——模板定义阶段的名称查找规则是核心:基类B<int>是一个非依赖类型(它的模板参数是具体的int,和派生类的模板参数无关),所以编译器在解析D的定义时,会直接找到基类B里的T(值为5),而不是派生类的模板参数T。
要让T指向派生类的模板参数,有两种直观的解决思路:
思路一:让基类成为依赖类型,延迟名称查找
把基类的模板参数改成依赖于派生类模板参数的类型,这样编译器会把基类的名称查找延迟到模板实例化阶段(此时派生类的模板参数已经确定),自然会优先选择派生类的T。
比如用std::integral_constant把派生类的模板参数包装成类型传给B:
#include <iostream> #include <type_traits> template <typename> struct B { constexpr static int T = 5; }; // 基类模板参数依赖于派生类的T,变成依赖类型 template <int T> struct D : B<std::integral_constant<int, T>> { constexpr static int value = T; }; int main() { std::cout << D<7>::value << std::endl; // 现在输出7 }
你也可以自定义一个依赖类型,核心就是让B的模板参数和D的模板参数挂钩,不一定非要用标准库工具。
思路二:显式限定T的作用域
直接在派生类里明确指定T是当前模板的参数,而不是基类的成员。因为模板参数属于当前类模板的作用域,所以用D::T(写法更清晰)即可:
#include <iostream> template <typename> struct B { constexpr static int T = 5; }; template <int T> struct D : B<int> { // 显式限定为派生类的模板参数T constexpr static int value = D::T; }; int main() { std::cout << D<7>::value << std::endl; // 输出7 }
这种方式更直接,不需要修改基类的使用方式,适合不想改动基类依赖关系的场景。
本质上这两种思路都是打破了“非依赖基类优先查找”的规则:要么让基类变成依赖类型延迟查找,要么直接指定名称的来源,让编译器优先选择派生类的模板参数。
内容的提问来源于stack exchange,提问作者mkmostafa
相关产品推荐
相关产品推荐

