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