C++的模板其实是个挺纠结的东西,用的不好的话,编译的一堆错误够你调到崩溃,但要是用的好呢,又确实非常方便,我们来看看
一.获取数组长度
比如
1 |
int arr[10]; |
怎么获取 arr 的长度呢?
最简单的代码:
1 |
uint32_t count = sizeof(arr) / sizeof(arr[0]); |
但是这样也带来一个问题,万一是个新手程序员:
1 2 |
int *p = arr; uint32_t count = sizeof(p) / sizeof(p[0]); |
就有问题了……
那么有没有办法,有一种安全的方法,当发现传入的是指针的时候,自动编译报错呢?
有的,模板里面可以推导出数组的长度。
所以我们可以使用如下代码
1 2 |
template <typename T, size_t N> size_t arrarysize(T (&array)[N]) { return N; } |
这样,当传入指针的时候,编译就会报错了。
而同时你肯定也能看出,我们甚至能指定只能传入数组长度为固定某数字的数组了,怎么做我就不用讲了吧?
二.切片函数
python中的切片函数真是令人怀念,并且即使传入的参数超过长度也不会崩溃,可是C++里面则就会出现问题,所以通常我们要把一个容器的数据做切片时,代码如下:
1 2 3 4 5 6 7 8 9 |
vector<int> src; vector<uint32_t> dst; uint32_t index; uint32_t count; vector<uint32_t>::iterator it_begin = src.begin() + index; vector<uint32_t>::iterator it_end = (it_begin + count) < src.end() ? (it_begin + count) : src.end(); dst.insert(dst.begin(), it_begin, it_end); |
注: 如果直接如下调用,会导致取到end()之后多余的数据
1 |
dst.insert(dst.begin(), src.begin() + index, src.begin() + index + count) |
其实这代码还是挺纠结,而且并不通用(各种类型的容器都要重复写代码),所以我们也可以用模板来优化一下,代码如下:
1 2 3 4 5 6 7 8 9 10 |
template <typename T, typename P> int Cut2Part(T& src, uint32_t index, uint32_t count, P& dst) { typeof(src.begin()) it_begin = src.begin() + index; typeof(src.begin()) it_end = (it_begin + count) < src.end() ? (it_begin + count) : src.end(); dst.insert(dst.begin(), it_begin, it_end); return 0; } |
可以注意到代码中使用了typeof,这也是C++挺好用的一个特性。
所以无论是什么类型的容器,只要如下调用即可
1 2 3 |
vector<int> src; list<uint32_t> dst; Cut2Part(src, index, count, dst) |
三.获取类名
当在使用模板,或者使用继承关系的类时,我们经常需要在打印Log时清楚的知道到底是哪个类的实例在执行。
所以我们可以用这个函数:
1 |
typeid(obj).name() |
如果实在类实例内部:
1 |
typeid(*this).name() |
OK,需要介绍的内容就是这样了~~
说句后话,python的确要比C++方便很多,但是在C++中经常会有这样的情景:在经过长时间尝试之后,“哇,原来这样能实现!”其实也是很不错的过程~比如之前的另一个宏定义:
1 2 3 4 |
#ifndef foreach #define foreach(container,it) \ for(typeof((container).begin()) it = (container).begin();it!=(container).end();++it) #endif |