c++11模板:容器(map,set,list,vector)中元素型別轉換
阿新 • • 發佈:2019-01-04
簡單的資料型別轉換很簡單,比如下面cast
模板函式族:
// 相同型別直接轉發
template<typename L>
L
cast(L left, typename std::decay<L>::type *) {
return std::forward<L>(left);
}
// 不同算術(數字)型別之間強制轉換
template<typename L, typename R>
typename std::enable_if<std::is_arithmetic<L>::value && std::is_arithmetic<R>::value,R>::type
cast(L left,R*right) {
return (R)left;
}
// 列舉型別強制轉換
template<typename L, typename R>
typename std::enable_if<std::is_enum<L>::value && std::is_enum<R>::value, R>::type
cast(L left, R*right) {
return (R)left;
}
// 數字轉字串
template<typename L>
typename std::enable_if<std::is_arithmetic<L>::value, std ::string>::type
cast(L left,std::string *right) {
std::ostringstream ss;
ss << left;
return ss.str();
}
// 字串轉數字
template<typename R>
typename std::enable_if<std::is_arithmetic<R>::value, R>::type
cast(const std::string &left, R *) {
std::istringstream ss(left);
R right;
ss >> right;
return right;
}
那麼對於容器型別,有沒有方便簡單的辦法呢?
c++11 <algorithm>
庫中的std::transform
函式就可以很方便的實現容器中元素型別的轉換,比如list
template<
typename L, // 源型別
typename R // 目標型別
>
std::list<R>cast(const std::list<L>&left, std::list<R>*) {
std::list<R> right;
std::transform(
left.begin(), // 輸入容器迭代器(開始)
left.end(), // 輸入容器迭代器(結尾)
std::insert_iterator<std::list<R>>(right, right.begin()), // 輸出迭代器
[](L l)->R {return cast(l, (R*)nullptr); } // lambda表示式呼叫上面的定義的Cast函式完成元素型別轉換
// 如果上面的cast函式無法滿足要求,請自行根據需要擴充套件。
);
return std::move(right);
}
對於std::set,std::vector
也是一樣的邏輯,只是把set
換成set
或vector
。
對於std::map
,邏輯是一樣的,但std::map有K,V兩個資料型別,所以程式碼上稍有不同:
template<
typename KL, // Key源型別
typename VL, // Value源型別
typename KR, // Key目標型別
typename VR> // Value目標型別
std::map<KR, VR>cast(const std::map<KL, VL>&left, std::map<KR, VR>*) {
std::map<KR, VR> right;
std::transform(
left.begin(), // 輸入entry迭代器開始
left.end(), // 輸入entry迭代器結尾
std::insert_iterator<std::map<KR, VR>>(right, right.begin()), // 輸出迭代器
[](std::pair<KL, VL> l)->std::pair<KR, VR> {
// 修改每個entry的key和value型別返回回新的鍵值對
return std::pair<KR, VR>(cast(l.first, (KR*)nullptr), cast(l.second, (VR*)nullptr));
}
);
return std::move(right);
}
呼叫示例
#include <algorithm>
#include <vector>
#include <list>
#include <set>
#include <map>
#include <sstream>
#include <type_traits>
#include <string>
int main(int argc, char *argv[]) {
// list呼叫示例
std::list<int> intlist{ 1,2,3,4,5 };
auto strlist2 = cast(intlist, (std::list<std::string>*)nullptr);
for (auto e : strlist2) {
std::cout << e << std::endl;
}
// map 呼叫示例
std::map<std::string, int> map1;
map1["88"] = 69;
map1["99"] = 199;
map1["100"] = 50;
// 轉換value型別 int->std::string
auto map2 = cast(map1, (std::map<std::string,std::string>*)nullptr);
std::cout << "map2 = "; print_map(map2);
// 轉換key,value型別
// std::string->int
// int -> std::string
auto map3 = cast(map1, (std::map<int,std::string>*)nullptr);
std::cout << "map3 = "; print_map(map3);
}