C++如何实现虚基模板类到派生模板类的转换,类似D语言opCast功能?
实现方案
C++ 可以通过模板特化做类型萃取+CRTP 奇异递归模板模式实现你要的效果,核心逻辑是先把类模板实例(比如 A<int>)拆解出模板名和参数类型,再绑定新的参数生成目标类型。
首先实现类型萃取器,用于拆分模板实例:
// 类型萃取:拆分 TemplateName<ParamType> 形式的类型 template <typename T> struct extract_template; // 特化匹配单参数类模板实例 template <template <typename> class TemplateName, typename ParamType> struct extract_template<TemplateName<ParamType>> { // 用新参数重新绑定模板 template <typename NewParam> using rebind = TemplateName<NewParam>; // 提取原参数类型 using original_param = ParamType; };
然后修改基类为 CRTP 形式,复用转换逻辑给所有子类:
#include <iostream> #include <stdexcept> // CRTP 第一个参数传入子类类型,第二个是当前存储的数据类型 template <typename Derived, typename T> class Base { protected: T data; // 改为protected让子类可访问 public: virtual void setData(T p_data) = 0; virtual ~Base() = default; // 虚析构必须实现,用默认实现即可 // 显式转换函数,NewT为目标参数类型 template <typename NewT> auto cast_to() const { using derived_traits = extract_template<Derived>; // 绑定新参数得到目标子类类型 using new_derived_type = typename derived_traits::template rebind<NewT>; // 转换数据并返回新实例 NewT converted_data = static_cast<NewT>(data); return new_derived_type(converted_data); } };
子类继承时传入自身类型即可复用转换逻辑,无需重复写代码:
template <typename T> class A : public Base<A<T>, T> { public: A(T data) { this->data = data; std::cout << data << std::endl; } void setData(T p_data) override { this->data = p_data; } }; // 其他8个子类都用同样的继承方式即可,不需要重复实现cast逻辑
测试效果:
int main() { A<int> a(123); // 输出 123 A<double> b = a.cast_to<double>(); // 输出 123 A<float> c = b.cast_to<float>(); // 输出 123 return 0; }
注意事项
- 上述萃取器只适配单参数类模板,如果你的子类是多参数模板,调整萃取器的特化参数数量即可
- 如果需要隐式转换,也可以把逻辑放到转换运算符里,但显式的
cast_to函数可读性更高,也避免隐式转换带来的意外问题 - 如果不想用CRTP,也可以在每个子类单独实现转换逻辑,代码结构和上述
cast_to函数一致即可
内容的提问来源于stack exchange,提问作者Wusiki Jeronii
相关产品推荐
相关产品推荐

