C++的模板其实是个挺纠结的东西

 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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章