標籤:

C++模板元編程--replace_type<>

在閱讀C++模板元編程的時候有一道題目如下:

實現一個模板類,具有以下形式

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++的工作

TAG:C | CC |