C++ 模板中的型別獲取(一)
阿新 • • 發佈:2019-01-27
C++ 模板中的型別獲取
1. 型別判斷
嚴格型別比較:
std::is_same<T1, T2>::value
cout << std::is_same<int, int>::value << endl; // true cout << std::is_same<int, long>::value << endl; // false cout << std::is_same<int, unsigned int>::value << endl; // false cout << std:
退化型別比較:
std::decay<T>::type
cout << std::is_same<int, std::decay<int>
2. 容器元素型別
STL 的容器支援:
Container::value_type
using type = Container::value_type;
3. 迭代器型別
- 標頭檔案:
#include <type_traits>
using type = std::iterator_traits<Itr>::value
4. 函式返回型別
std::result_of<Func()>::type
5. 舉兩栗子
判斷STL容器是否包含某元素:
- 當容器元素為基本型別時:
// map::value_type is const std::pair<const T, T> // need reload operator "==" to pass compile template <class T> bool operator==(const pair<const T,T> p1, const pair<T,T> p2){ return p1.first==p2.first && p1.second==p2.second; } // basic value type template <class Container, class ItemType> int isContain(Container const &container, ItemType const &item){ using type = typename std::decay<typename Container::value_type>::type; bool isSame = std::is_same<type, typename std::decay<ItemType>::type>::value; if(!isSame){ cout << "error type not same " << endl; return -1; } else { int index=0; for(auto itr = container.begin();itr != container.end();){ if(*itr == item){ break; } else { itr++; index++; } } return index; } };
- 當元素型別為自定義的class或struct時:
// user defined value type template <class Container, class ItemType> int isContain(Container const &container, ItemType const &item, bool func(ItemType const, ItemType const)){ using type = typename std::decay<typename Container::value_type>::type; bool isSame = std::is_same<type, typename std::decay<ItemType>::type>::value; if(!isSame){ cout << "error type not same " << endl; return -1; } else { int index=0; for(auto itr = container.begin();itr != container.end();){ if(func(*itr, item)){ break; } else { itr++; index++; } } return index; } };
對STL容器的元素求和:
元素為基本型別時,用
std::accumulate(container.begin(), container.end(), 0);
即可,當元素為自定義的型別時:
template <typename Container, typename ItemType> ItemType accumulate(Container container, ItemType getValue){ ItemType sum; for (int i = 0; i < container.size(); ++i) { sum += getValue(container.at(i)); } return sum; }
struct Pt{ int x; int y; } int getValue(Pt pt){ return pt.x;} int main(){ vector<Pt> pts = {{1,2}, {2,3}, {3,4}}; auto sum = accumulate(pts,getValue); // 執行OK return 0; }
這樣寫模板函式,type ItemType 當作函式的返回型別, 傳入匿名(lambda) 函式時會報錯不能通過編譯
mismatched types ... main()::<lambda(int)>
例如:auto getValueX = [](Pt pt)->int{return pt.x;}; auto sum = accumulate(pts,getValueX);
或者:
auto sum = accumulate(pts,[](Pt pt){return pt.x;});
所以模板函式傳入的函式應該是函式指標型別, 返回型別用
std::result_of
獲取:template<typename Container, typename Func> auto add(Container& container, Func getValue) -> typename std::result_of<Func(typename Container::value_type)>::type { using type = typename std::result_of<Func(typename Container::value_type)>::type; type sum = getValue(container.at(0)); for (int i = 0; i < container.size(); ++i) { sum += getValue(container.at(i)); } return sum; }