如何实现含3×2个基对象且各带get函数的递归模板Special实例?
解决C++二维递归模板的基对象展开问题
嘿,我来帮你搞定这个递归模板的需求!首先咱们得先看看你原代码的问题在哪,然后一步步调整到你想要的效果——让Special<3,2>包含3×2个基对象,每个都有get()函数。
原代码的核心问题
你的原模板只在N维度做了递归继承,M维度完全没展开:
Special<M,N>只继承Special<M,N-1>,所以Special<3,2>的基类链是Special<3,1>→Special<3,0>,但你只特化了Special<0,0>,Special<3,0>根本没有定义,编译直接报错。- 就算编译能过,也只能得到3个基对象(
Special<3,2>、Special<3,1>、Special<3,0>),远达不到3×2=6个的要求。
解决方案:二维递归继承 + 避免重复基类
要生成M×N个基对象,必须在M和N两个维度都做递归。另外,多重递归继承会导致同一个基类被多次继承(比如Special<1,1>会被Special<2,1>和Special<1,2>同时继承),所以我们需要用虚继承来确保每个基类只实例化一次。
版本1:包含所有0≤m≤3、0≤n≤2的基对象(共4×3=12个)
这个版本是通用的二维递归模板,适合需要完整维度展开的场景:
#include <iostream> // 最基础的终止特化:M=0且N=0 template <> class Special<0, 0> { public: void* get() { std::cout << "Special<0,0>::get()" << std::endl; return this; } }; // M维度递归(N=0时) template <unsigned int M> class Special<M, 0> : public virtual Special<M-1, 0> { public: void* get() { std::cout << "Special<" << M << ",0>::get()" << std::endl; return static_cast<Special<M-1, 0>*>(this); } }; // N维度递归(M=0时) template <unsigned int N> class Special<0, N> : public virtual Special<0, N-1> { public: void* get() { std::cout << "Special<0," << N << ">::get()" << std::endl; return static_cast<Special<0, N-1>*>(this); } }; // 通用二维递归:同时展开M和N维度,虚继承避免重复基类 template <unsigned int M, unsigned int N> class Special : public virtual Special<M-1, N>, public virtual Special<M, N-1> { public: void* get() { std::cout << "Special<" << M << "," << N << ">::get()" << std::endl; // 可根据需求返回任意基类指针,这里返回M-1,N维度的基类 return static_cast<Special<M-1, N>*>(this); } }; int main() { Special<3, 2> specialobj; // 测试调用所有基类的get()函数(需显式转换避免名字隐藏) static_cast<Special<0,0>&>(specialobj).get(); static_cast<Special<1,0>&>(specialobj).get(); static_cast<Special<2,0>&>(specialobj).get(); static_cast<Special<3,0>&>(specialobj).get(); static_cast<Special<0,1>&>(specialobj).get(); static_cast<Special<1,1>&>(specialobj).get(); static_cast<Special<2,1>&>(specialobj).get(); static_cast<Special<3,1>&>(specialobj).get(); static_cast<Special<0,2>&>(specialobj).get(); static_cast<Special<1,2>&>(specialobj).get(); static_cast<Special<2,2>&>(specialobj).get(); static_cast<Special<3,2>&>(specialobj).get(); return 0; }
版本2:严格3×2个基对象(1≤m≤3、1≤n≤2)
如果你只需要刚好6个基对象,把终止特化改成Special<1,1>即可,这样递归只会展开到Special<3,2>:
#include <iostream> // 基础特化:M=1且N=1,作为递归起点 template <> class Special<1, 1> { public: void* get() { std::cout << "Special<1,1>::get()" << std::endl; return this; } }; // M维度递归(N=1时) template <unsigned int M> class Special<M, 1> : public Special<M-1, 1> { public: void* get() { std::cout << "Special<" << M << ",1>::get()" << std::endl; return static_cast<Special<M-1, 1>*>(this); } }; // N维度递归(M=1时) template <unsigned int N> class Special<1, N> : public Special<1, N-1> { public: void* get() { std::cout << "Special<1," << N << ">::get()" << std::endl; return static_cast<Special<1, N-1>*>(this); } }; // 通用二维递归:展开M>1且N>1的情况 template <unsigned int M, unsigned int N> class Special : public Special<M-1, N>, public Special<M, N-1> { public: void* get() { std::cout << "Special<" << M << "," << N << ">::get()" << std::endl; return static_cast<Special<M-1, N>*>(this); } }; int main() { Special<3, 2> specialobj; // 调用6个目标基对象的get()函数 static_cast<Special<1,1>&>(specialobj).get(); static_cast<Special<1,2>&>(specialobj).get(); static_cast<Special<2,1>&>(specialobj).get(); static_cast<Special<2,2>&>(specialobj).get(); static_cast<Special<3,1>&>(specialobj).get(); static_cast<Special<3,2>&>(specialobj).get(); return 0; }
关键说明
- 每个基类都有独立的
get()函数,你可以通过显式类型转换调用任意基类的get(),证明它们都存在于specialobj实例中。 - 虚继承的作用是避免同一个基类被多次实例化,减少冗余并避免歧义。
内容的提问来源于stack exchange,提问作者zhangxiaoguo
相关产品推荐
相关产品推荐

