c++ 模板 指针类型偏特化
2023-03-20 15:35:48 时间
一步步来,先简单点.
目标:我们要实现一个模板类,例化后,可以通过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*)
");
}
heap_node(ref_type d) :data(&d){
printf("<T> (T)
");
}
};
int main() {
A a(10);
printf("ptr=%p
",&a);
heap_node<A> p0(a);
printf("ptr=%p val=%d
", p0.get_ptr(),p0.get_val().data);
heap_node<A> p1(&a);
printf("ptr=%p val=%d
", p1.get_ptr(), p1.get_val().data);
/* 这里有问题
heap_node<A*> p2(a);
printf("ptr=%p val=%d
", p2.get_ptr(), p2.get_val().data);
heap_node<A*> p3(&a);
printf("ptr=%p val=%d
", 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*)
");
}
heap_node(ref_type d) :data(&d){
printf("<T> (T)
");
}
};
//<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*)
");
}
heap_node(ref_type d) :data(&d){
printf("<T*> (T)
");
}
};
int main() {
A a(10);
printf("ptr=%p
",&a);
heap_node<A> p0(a);
printf("ptr=%p val=%d
", p0.get_ptr(),p0.get_val().data);
heap_node<A> p1(&a);
printf("ptr=%p val=%d
", p1.get_ptr(), p1.get_val().data);
heap_node<A*> p2(a);
printf("ptr=%p val=%d
", p2.get_ptr(), p2.get_val().data);
heap_node<A*> p3(&a);
printf("ptr=%p val=%d
", p3.get_ptr(), p3.get_val().data);
char ch = getchar();
}
可能还有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*)
");
}
heap_node(ref_type d) :data(&d){
printf("<T> (T)
");
}
};
int main() {
A a(10);
//自定义类 A 测试
printf("ptr=%p
",&a);
heap_node<A> p0(a);
printf("ptr=%p val=%d
", p0.get_ptr(),p0.get_val().data);
heap_node<A> p1(&a);
printf("ptr=%p val=%d
", p1.get_ptr(), p1.get_val().data);
heap_node<A*> p2(a);
printf("ptr=%p val=%d
", p2.get_ptr(), p2.get_val().data);
heap_node<A*> p3(&a);
printf("ptr=%p val=%d
", p3.get_ptr(), p3.get_val().data);
//内建类 int 测试
int b = 100;
printf("==========int====
ptr=%p
", &b);
heap_node<int> p4(b);
printf("ptr=%p val=%d
", p4.get_ptr(), p4.get_val());
heap_node<int> p5(&b);
printf("ptr=%p val=%d
", p5.get_ptr(), p5.get_val());
heap_node<int*> p6(b);
printf("ptr=%p val=%d
", p6.get_ptr(), p6.get_val());
heap_node<int*> p7(&b);
printf("ptr=%p val=%d
", p7.get_ptr(), p7.get_val());
//内建类 string 测试
string str = "string";
printf("==========str====
ptr=%p %s
", &str,str);
heap_node<string> s4(str);
printf("ptr=%p val=%s
", s4.get_ptr(), s4.get_val());
heap_node<string> s5(&str);
printf("ptr=%p val=%s
", s5.get_ptr(), s5.get_val());
heap_node<string*> s6(str);
printf("ptr=%p val=%s
", s6.get_ptr(), s6.get_val());
heap_node<string*> s7(&str);
printf("ptr=%p val=%s
", s7.get_ptr(), s7.get_val());
//const int 测试
const int c = 123;
printf("==========const int====
ptr=%p
", &c);
heap_node<const int> c4(c);
printf("ptr=%p val=%d
", c4.get_ptr(), c4.get_val());
heap_node<const int> c5(&c);
printf("ptr=%p val=%d
", c5.get_ptr(), c5.get_val());
heap_node<const int*> c6(c);
printf("ptr=%p val=%d
", c6.get_ptr(), c6.get_val());
heap_node<const int*> c7(&c);
printf("ptr=%p val=%d
", c7.get_ptr(), c7.get_val());
char ch = getchar();
}
相关文章
- 不懂程序看的明白《黑客帝国》吗?
- 假如你想成为全栈工程师…
- JavaMail 保证邮件发送成功的方法总结
- 如何让你的程序员不要厌倦工作?
- 程序员最恐怖的噩梦是什么?
- 15 个实用的 PHP 正则表达式
- 程序体积优化的十个小妙招
- Java 9因模块化进程缓慢而欲推迟发布
- 写在 PHP7 发布之际一些话
- 这些 Nginx 负载均衡配置误区,运维请注意
- 有人在Github上用几行代码就造了个锤子便签
- 做过程序员的产品经理是一种什么样的存在?
- PHPUnit 在 Windows 下的配置及使用教程
- 程序开发人员缺乏经验的7种表现
- 一个单例还能写出花来吗?
- 关于容器,你需要知道这7件事
- 程序员如何在职场中实现“跨越式”成长?
- 成为一名更好的程序员:如何阅读源代码
- Kubernetes 集群网络从懵圈到熟悉,看这一篇就够了
- 一个印度程序员的生活领悟