一步步来,先简单点.
目标:我们要实现一个模板类,例化后,可以通过get_val获取到值,通过get_ptr获取到指针.具体什么意思结合例子来看看吧.
例子
//一个普通类 struct A{ int data; A(int _data = 0):data(_data){} }; //主角 template <typename T> class heap_node{ public: typedef T val_type; typedef T* ptr_type; typedef T& ref_type; ptr_type data; ref_type get_val() { return *data; } ptr_type get_ptr() { return data; } heap_node(ptr_type d) :data(d){ printf("<T> (T*)\n"); } heap_node(ref_type d) :data(&d){ printf("<T> (T)\n"); } }; int main() { A a(10); printf("ptr=%p\n",&a); heap_node<A> p0(a); printf("ptr=%p val=%d\n", p0.get_ptr(),p0.get_val().data); heap_node<A> p1(&a); printf("ptr=%p val=%d\n", p1.get_ptr(), p1.get_val().data); /* 这里有问题 heap_node<A*> p2(a); printf("ptr=%p val=%d\n", p2.get_ptr(), p2.get_val().data); heap_node<A*> p3(&a); printf("ptr=%p val=%d\n", p3.get_ptr(), p3.get_val().data); */ char ch = getchar(); }
(不要在类里直接保存值类型的数据,可以用指针或者引用都可以)
我们要达到自适应的效果,比如现在有A a(10);
通过下面的四种方式,都能通过p.get_val()得到a的值10,
通过p.get_ptr()得到a的地址.heap_node<A> p(a) | heap_node<A> p(&a) | heap_node<A*> p(a) | heap_node<A*> p(&a)
发现heap_node<A *> p2(a)
或者heap_node<A *> p3(&a)
的时候,无法正常表达我们原来的意识,
比如 heap_node<A *> p2(a)
=>T = A *
所以 val_type 变成了 A *,ptr_type 变成了 A * *,
ref_type get_val() { return *data; }
ptr_type get_ptr() { return data; }
怎么解决呢.需要对<T *>特殊处理一下.
struct A{ int data; A(int _data = 0):data(_data){} }; template <typename T> class heap_node{ public: typedef T val_type; typedef T* ptr_type; typedef T& ref_type; ptr_type data; ref_type get_val() { return *data; } ptr_type get_ptr() { return data; } heap_node(ptr_type d) :data(d){ printf("<T> (T*)\n"); } heap_node(ref_type d) :data(&d){ printf("<T> (T)\n"); } }; //<T*>偏特化 template <typename T> class heap_node<T*>{ public: typedef T val_type; typedef T* ptr_type; typedef T& ref_type; ptr_type data; ref_type get_val() { return *data; } ptr_type get_ptr() { return data; } heap_node(ptr_type d) :data(d){ printf("<T*> (T*)\n"); } heap_node(ref_type d) :data(&d){ printf("<T*> (T)\n"); } }; int main() { A a(10); printf("ptr=%p\n",&a); heap_node<A> p0(a); printf("ptr=%p val=%d\n", p0.get_ptr(),p0.get_val().data); heap_node<A> p1(&a); printf("ptr=%p val=%d\n", p1.get_ptr(), p1.get_val().data); heap_node<A*> p2(a); printf("ptr=%p val=%d\n", p2.get_ptr(), p2.get_val().data); heap_node<A*> p3(&a); printf("ptr=%p val=%d\n", p3.get_ptr(), p3.get_val().data); char ch = getchar(); } CPP 折叠 复制 全屏
可能还有const修饰T,或者实例化T为原始数据类型......,都可能出现类似的问题,可以用偏特化解决.这里就不一一列举出来哈.
我们可以发现,特例化的<T*>模板与原模板代码上几乎一样的,如果特殊情况比较多,需要多特例化几次,那代码不得copy出多份,然后小改一下.我个人感觉不太好.是不是可以小小优化一下呢?
直接上代码:
struct A{ int data; A(int _data = 0):data(_data){} }; //这个是通用的类型自适应处理,与class heap_node没有强制关系, 也可以用在其他自定义类上 template <class T> struct heap_node_type{ typedef T val_type; typedef T* ptr_type; typedef T& ref_type; }; template <class T> struct heap_node_type<T*>{ typedef T val_type; typedef T* ptr_type; typedef T& ref_type; }; //继承一下heap_node_type //这时候heap_node<A*> p2(a) =>先进父类heap_node_type<A*>,val_type 还是A, //ptr_type 还是 A* template <class T> class heap_node :heap_node_type<T>{ public: ptr_type data; ref_type get_val() { return *data; } ptr_type get_ptr() { return data; } heap_node(ptr_type d) :data(d){ printf("<T> (T*)\n"); } heap_node(ref_type d) :data(&d){ printf("<T> (T)\n"); } }; int main() { A a(10); //自定义类 A 测试 printf("ptr=%p\n",&a); heap_node<A> p0(a); printf("ptr=%p val=%d\n", p0.get_ptr(),p0.get_val().data); heap_node<A> p1(&a); printf("ptr=%p val=%d\n", p1.get_ptr(), p1.get_val().data); heap_node<A*> p2(a); printf("ptr=%p val=%d\n", p2.get_ptr(), p2.get_val().data); heap_node<A*> p3(&a); printf("ptr=%p val=%d\n", p3.get_ptr(), p3.get_val().data); //内建类 int 测试 int b = 100; printf("==========int====\nptr=%p\n", &b); heap_node<int> p4(b); printf("ptr=%p val=%d\n", p4.get_ptr(), p4.get_val()); heap_node<int> p5(&b); printf("ptr=%p val=%d\n", p5.get_ptr(), p5.get_val()); heap_node<int*> p6(b); printf("ptr=%p val=%d\n", p6.get_ptr(), p6.get_val()); heap_node<int*> p7(&b); printf("ptr=%p val=%d\n", p7.get_ptr(), p7.get_val()); //内建类 string 测试 string str = "string"; printf("==========str====\nptr=%p %s\n", &str,str); heap_node<string> s4(str); printf("ptr=%p val=%s\n", s4.get_ptr(), s4.get_val()); heap_node<string> s5(&str); printf("ptr=%p val=%s\n", s5.get_ptr(), s5.get_val()); heap_node<string*> s6(str); printf("ptr=%p val=%s\n", s6.get_ptr(), s6.get_val()); heap_node<string*> s7(&str); printf("ptr=%p val=%s\n", s7.get_ptr(), s7.get_val()); //const int 测试 const int c = 123; printf("==========const int====\nptr=%p\n", &c); heap_node<const int> c4(c); printf("ptr=%p val=%d\n", c4.get_ptr(), c4.get_val()); heap_node<const int> c5(&c); printf("ptr=%p val=%d\n", c5.get_ptr(), c5.get_val()); heap_node<const int*> c6(c); printf("ptr=%p val=%d\n", c6.get_ptr(), c6.get_val()); heap_node<const int*> c7(&c); printf("ptr=%p val=%d\n", c7.get_ptr(), c7.get_val()); char ch = getchar(); }