C++之型別萃取技巧
阿新 • • 發佈:2019-01-25
在我們前面寫順序表的時候會產生一個問題。
使用型別萃取的原因
就是當你的順序表是自定義型別,我們進行順序表增容的時候,這個時候會出現一個問題,比如string型別,這個型別中有一個_buf與_ptr,當儲存少於16個的時候這時會儲存在_buf當中的,如果多於16個,那個會單獨開闢空間,進行儲存,這時拷貝的時候就是拷貝過去這個儲存的地址而已,所以這樣呼叫解構函式的時候,當增加容量的時候,這個時候會把儲存string的那塊空間進行釋放。會造成資料丟失的問題。
所以,在這裡面我們提到一個型別萃取的技巧,可以把自定義型別和內建型別的區分開,然後對自定義型別的使用for迴圈拷貝,對於內建型別的,採用memcpy的方式進行拷貝。
示例:
#include<iostream>
#include<stdlib.h>
using namespace std;
//型別萃取
struct __truetype
{
bool get()
{
return true;
}
};
struct __falsetype
{
bool get()
{
return false;
}
};
template<typename T>
struct typetraits
{
typedef __falsetype __ispodtype;
};
template <>
struct typetraits<int >
{
typedef __truetype __ispodtype;
};
template<>
struct typetraits<char >
{
typedef __truetype __ispodtype;
};
template<>
struct typetraits<short >
{
typedef __truetype __ispodtype;
};
template<>
struct typetraits<bool >
{
typedef __truetype __ispodtype;
};
template<>
struct typetraits<unsigned int >
{
typedef __truetype __ispodtype;
};
template<>
struct typetraits<unsigned short >
{
typedef __truetype __ispodtype;
};
template<>
struct typetraits<unsigned long >
{
typedef __truetype __ispodtype;
};
template<>
struct typetraits<long >
{
typedef __truetype __ispodtype;
};
template<>
struct typetraits<long long >
{
typedef __truetype __ispodtype;
};
template<>
struct typetraits<unsigned long long >
{
typedef __truetype __ispodtype;
};
template<>
struct typetraits<long double >
{
typedef __truetype __ispodtype;
};
template<>
struct typetraits<double >
{
typedef __truetype __ispodtype;
};
template<>
struct typetraits<float >
{
typedef __truetype __ispodtype;
};
template<typename T>
void Copy(const T*src, T* dst, size_t size)
{
if (typetraits<T>::__ispodtype().get())
{
cout << "__truetype:" << typeid(T).name() << endl;
memcpy(dst, src, size*sizeof(T));
}
else
{
cout << "__falsetype:" << typeid(T).name() << endl;
for (size_t i = 0; i < size; i++)
{
dst[i] = src[i];
}
}
}
void test()
{
int a1[8] = { 1, 2, 3, 4, 5, 6 };
int a2[8] = { 9, 5, 6, 7, 8, 2, 2 };
Copy(a1, a2, 3);
cout << a2<<endl;
string c1[10] = {"123","7989465","456321","4561","4563"};
string c2[5] = {"654","312","a"};
Copy(c1, c2, 3);
}
int main()
{
test();
system("pause");
return 0;
}
在這裡我們採用了模板的特化,這裡使用了全特化,直接給int,double等內建型別做特化。
在這裡我們設定內建型別是truetype,設定自定義型別是falsetype,然後我們通過不同的型別利用get()函式返回不同的布林值,這樣對內建型別採用memcp拷貝,對於非內建型別,採用for迴圈拷貝,這樣就能實現我們想要的結果了。