C++中的萃取機制(traits)
阿新 • • 發佈:2019-02-15
由來
在設計迭代器(iterator)時,考慮到需要經常訪問迭代器所指物件之型別,稱之為該迭代器的value_type
,利用內嵌型別宣告typedef可輕鬆實現隱藏所指物件型別:
template<typename T>
struct Iterator
{
typedef T value_type;
}
如此一來,泛型演算法便可通過typename Iterator<T>::value_type
獲取value_type
:
template<typename Iterator>
typename Iterator::value_type getValue(Iterator iter)
{
return *iter;
}
在客戶端,我們可做如下形式的呼叫:
vector<int> ivec{0, 1, 2, 3};
int val = getValue(ivec.begin());
STL要求,支援迭代器的演算法,也應該支援原生指標,比如:
int arr[] = {0, 1, 2};
int val = getValue(arr+1);
# 此時編譯器會報錯
因為int*
型別(也即原生指標)不能內嵌型別宣告,這裡需要多一層的封裝,萃取編譯技術應運而生。進一步封裝,便可進一步特化。
template<typename Iterator>
struct iterator_traits
{
typedef typename Iterator::value_type value_type;
};
// 特化版本一,針對原生指標型別
template<typename T>
struct iterator_triats<T*>
{
typedef T value_type;
};
// 特化版本二,
template<typename T>
struct iterator_traits<const T*>
{
typedef T value_type;
};
// 重寫getValue()方法
template<typename Iterator>
typename iterator_traits<Iterator>::value_type getValue(Iterator iter)
{
return *iter;
}
這時便可實現對原生指標型別的支援:
int val = getValue(arr+1);
型別萃取(type traits)
struct __true_type{};
struct __false_type{};
template<typename T>
struct __type_traits
{
typedef __false_type has_trivial_default_constructor;
typedef __false_type has_trivial_destructor;
};
template<>
struct __type_traits<int>
{
typedef __true_type has_trivial_default_constructor;
typedef __true_type has_trivial_destructor;
};