C++模板元編程--replace_type<>
實現一個模板類,具有以下形式
replace_type<c, x, y>n
使得
replace_type<c, x, y>::typen
為將複合類型 c 中的所有 x 類型替換為 y,
複合類型通常指由其他類型定義的類型,例如類型T可以定義複合類型T* T& T[]。通常複合類型指指針,數組,引用,和。
舉兩個例子
replace_type<int, int, float>::type t1; //t1 為 floatnreplace_type<int*&, int, float>::type t2; //t2 為 float*&n
下面是實現。
首先普遍情況,c 類型中不包含 x 類型:
template<class c, class x, class y>nstruct replace_type {nttypedef c type;n};n
這樣處理了typedef
開始迷之偏特化,當 c 類型與 x 類型相同時,直接替換
template<class x, class y>nstruct replace_type<x, x, y> {nttypedef y type;n};n
繼續迷之偏特化,當 c 類型為 x 類型的指針,引用,或數組時
template<class x, class y>nstruct replace_type<x*, x, y> {nttypedef y* type;n};nntemplate<class x, class y>nstruct replace_type<x&, x, y> {nttypedef y& type;n};nntemplate<class x, class y, size_t N>nstruct replace_type<x[N], x, y> {nttypedef y type[N];n};n
然後開始迷之偏特化+遞歸,當 c 為指針類型,引用類型,或數組但並不直接是 x 的指針引用或數組時,例如 c 是 int ***,x 是 int 時,上面的代碼無法處理這種情況。此時需要遞歸去掉指針,並獲取類型後加回去,具體如下:
template<class c, class x, class y>nstruct replace_type<c*, x, y> {nttypedef typename nttreplace_type<c, x, y>::type* type;n};nntemplate<class c, class x, class y>nstruct replace_type<c&, x, y> {nttypedef typenamenttreplace_type<c, x, y>::type& type;n};nntemplate<class c, class x, class y, size_t N>nstruct replace_type<c[N], x, y> {nttypedef typename nttreplace_type<c, x, y>::type type[N];n}n
此時,我們的代碼已經可以處理大部分的情況了,譬如這樣用:
replace_type<const int****&, const int, volatile float>::type t3;n//t3類型:volatile float****&n
再給力一點,處理一下函數,對於無參函數,可以這樣偏特化
template<class r, class x, class y >nstruct replace_type<r(), x, y> {nttypedef typenamenttreplace_type<r, x, y>::type type();n}n
而對於有參函數,不得不祭出我最討厭的變長模板參數來處理。
template<class r, class x, class y, class ...Args>nstruct replace_type<r(Args...), x, y> {nttypedef typename replace_type<r, x, y>::type ntttype (typename replace_type<Args, x, y>::type...);n}n
這樣,連函數參數裡面的類型也可以替換掉了。
下面給出一組測試用例。
#include<type_traits>n#include<iostream>n#include<vector>nnusing std::cout;nusing std::endl;nnint main() {ntstd:: cout << std::boolalpha;nt//int*** to float***ntcout << std::is_same<replace_type<int***, int, float>::type, float***>::value << endl;nt//int[1][2][3] to float[1][2][3]ntcout << std::is_same<replace_type<int[1][2][3], int, float>::type, float[1][2][3]>::value << endl;nt//int****& to float****&ntcout << std::is_same<replace_type<int****&, int, float>::type, float****&>::value << endl;nt//const int ****& to volatile float****&ntcout << std::is_same<replace_type<const int****&, const int, volatile float>::type, volatile float****&>::value << endl;nt//int**&() to double**&()ntcout << std::is_same<replace_type<int**&(), int, double>::type, double**&()>::value << endl;nt//int**&(int) to double**&(double)ntcout << std::is_same<replace_type<int**&(int), int, double>::type, double**&(double)>::value << endl;nt//int**&(int, int*, int[]) to double**&(double, double*, double[])ntcout << std::is_same<replace_type<int**&(int, int*, int[]), int, double>::type, double**&(double, double*, double[])>::value << endl;nt//int(*&)(int(*&)(int)) to double(*&)(double(*&)(double))ntcout << std::is_same<replace_type<int(*&)(int(*&)(int)), int, double>::type, double(*&)(double(*&)(double))>::value << endl;nt//const double*& to std::vector<int>*&ntcout << std::is_same<replace_type<const double*&, const double, std::vector<int>>::type, std::vector<int>*&>::value << endl;n return 0;n}n
全劇終。
推薦閱讀:
※C++模板元編程---編譯期類成員檢測
※萌新刷題(一)A + B 問題
※刷題大戰 09 代碼評審報告
※std::make_index_sequence的簡單實現和簡單應用
※GacUI:初步完成Workflow腳本轉C++的工作
