在C++中,我們經常遇到需要對一個對象數組進行複製,比如下面一個結構:
struct STest{ int a; int b; vector<int> vctInt;};
我們定義了兩個數組:
STest A[20];STest B[20];
需要將數組A中的所有內容複寫到B數組中,通常我們的做法都是這樣:
for(size_t i = 0; i < ARRAYSIZE(A); ++i){ A[i] = B[i];}
這裡不能直接使用memcpy,因為STest中有vector類型。但是,如果我們定義的是內建類型的數組,則上面的代碼效率較低,而直接使用memcpy會更高效。
為瞭解決上面的問題,我們可以使用C++模板對不同的類型進行不同的處理。下面有兩種寫法:
第一種寫法是最容易想到的,就是直接寫一個模板,並對這個模板的C++內建類型進行特化處理:
template<typename T,size_t N>inline void ArrayAssign(T (&A)[N], T (&B)[N]){ for(size_t i = 0; i < N; ++i) A[i] = B[i];}template<size_t N>inline void ArrayAssign(bool (&A)[N], bool (&B)[N]){ memcpy(A,B,sizeof(A));}template<size_t N>inline void ArrayAssign(char (&A)[N], char (&B)[N]){ memcpy(A,B,sizeof(A));}template<size_t N>inline void ArrayAssign(short (&A)[N], short (&B)[N]){ memcpy(A,B,sizeof(A));}template<size_t N>inline void ArrayAssign(int (&A)[N], int (&B)[N]){ memcpy(A,B,sizeof(A));}template<size_t N>inline void ArrayAssign(long long (&A)[N], long long (&B)[N]){ memcpy(A,B,sizeof(A));}template<size_t N>inline void ArrayAssign(unsigned char (&A)[N], unsigned char (&B)[N]){ memcpy(A,B,sizeof(A));}template<size_t N>inline void ArrayAssign(unsigned short (&A)[N], unsigned short (&B)[N]){ memcpy(A,B,sizeof(A));}template<size_t N>inline void ArrayAssign(unsigned int (&A)[N], unsigned int (&B)[N]){ memcpy(A,B,sizeof(A));}template<size_t N>inline void ArrayAssign(unsigned long long (&A)[N],unsigned long long (&B)[N]){ memcpy(A,B,sizeof(A));}
下面是第二種寫法,這種寫法,把內建類型的判斷提出來,可以方便其它地方使用:
template<bool A,typename B,typename C>struct _if{};template<typename B,typename C>struct _if<true,B,C>{ typedef B Type; };template<typename B,typename C>struct _if<false,B,C>{ typedef C Type; };template<typename T,size_t N>inline size_t ARRAYSIZE(T (&)[N]){ return N;}template<typename T>struct IsInnerType { static const bool Value = false; };template<>struct IsInnerType<bool> { static const bool Value = true; };template<>struct IsInnerType<char> { static const bool Value = true; };template<>struct IsInnerType<short> { static const bool Value = true; };template<>struct IsInnerType<int> { static const bool Value = true; };template<>struct IsInnerType<long long> { static const bool Value = true; };template<>struct IsInnerType<unsigned char> { static const bool Value = true; };template<>struct IsInnerType<unsigned short> { static const bool Value = true; };template<>struct IsInnerType<unsigned int> { static const bool Value = true; };template<>struct IsInnerType<unsigned long long> { static const bool Value = true; };template<typename T,size_t N>struct ArrayAssignInnerType{ static inline void Invoke(T (&A)[N], T (&B)[N]) { memcpy(A,B,sizeof(A)); }};template<typename T,size_t N>struct ArrayAssignCustomType{ static inline void Invoke(T (&A)[N], T (&B)[N]) { for(size_t i = 0; i < N; ++i) A[i] = B[i]; }};template<typename T,size_t N>inline void ArrayAssign(T (&A)[N], T (&B)[N]){ _if<IsInnerType<T>::Value,ArrayAssignInnerType<T,N>,ArrayAssignCustomType<T,N> >::Type::Invoke(A,B);}
經過上面的處理,我們可以不用擔心效率問題;同時,寫起來也方便很多,而且不會出錯。直接按如下寫就OK了:
ArrayAssign(B,A);
以上代碼在VC和GCC下編譯通過。