模板作為C++語言特性的一個重要組成部分甸鸟,被廣泛用在范式編程中,在標(biāo)準(zhǔn)庫中經(jīng)扯妮海可以看到一些非常讓人拍案叫絕的模板技術(shù)。在課程中接觸到這些技術(shù)松嘶,做個整理和總結(jié)艘狭。
一. variadic templates
實現(xiàn)這一特性的方法是通過遞歸算法,一次處理一個目標(biāo)參數(shù)翠订,直到處理到最后的模板參數(shù)作為遞歸基返回巢音。
以標(biāo)準(zhǔn)庫的hash函數(shù)為例
template<typename... Types>
size_t hash_all(const Types&... args)
{
size_t seed=0;
hash_val(seed,args...); //進(jìn)入計算
return seed;
}
template<typename T,typename... Types>
void hash_val(size_t &seed,
const T& val,const Types&... args)
{
//處理第一個模板參數(shù)
hash_combine(seed,val);
//遞歸
hash_val(sed,args...);
}
//處理到最后一個參數(shù)
template<typename T>
void hash_val(size_t &seed,const T& val)
{
hash_combine(seed,val);
}
//對模板參數(shù)進(jìn)行處理
#include <functional>
template<typename T>
void hash_combine(size_t &seed,const T &val)
{
seed^=std::hash<T>()(val)+0x9e3779b9
+(seed<<6)+(seed>>2);
}
二. tuple的參數(shù)處理
template<typename... Values> class tuple;
//繼承鏈的最頂端
template<> class tuple<>{};
template<typename Head,typename... Tail>
class tuple<Head,Tail...>
:private tuple<Tail...>
{
typedef tuple<Tail...> inherited;
public:
tuple(){}
tuple(Head v,Tail... vtail)
:m_head(v),inherited(vtail...){}
typename Head::type head() { return m_head; }
inherited &tail() { return *this; }
protected:
Head m_head;
};
tuple的設(shè)計是利用繼承鏈的最低端,在構(gòu)造函數(shù)中對它的直接基類進(jìn)行初始化尽超,而它的基類又對基類的直接基類進(jìn)行初始化官撼,不斷遞歸,直到直接基類是個空類為止似谁。
//以tuple(1,2.3,"hello")為例
tuple<int,float,string> t(1,2.3,"hello");
t.head() ; //1
t.tail(); //(2.3,"hello")
t.tail().head(); //2.3
三. type traits的設(shè)計
標(biāo)準(zhǔn)庫為我們提供了很多的type traits的模板類型歧寺,我們可以用來初始化獲得類型的相關(guān)信息燥狰。
以 is_void為例,用來判斷是不是void類型斜筐,解決思路是把對象的一些其他類型去除再來判斷是否為void
//去除 const 的屬性
template<typename T>
struct remove_const
{
typedef T type;
};
template<typename T>
struct remove_const<T const>
{
typedef T type;
};
//去除 volatile 的屬性
template<typename T>
struct remove_volatile
{
typedef T type;
};
template<typename T>
struct remove_volatile<T volatile>
{
typedef T type;
};
//去除 const volatile 的屬性
template<typename T>
struct remove_cv
{
typedef typename remove_const<typename remove_volatile<T>::type>::type type;
};
template<typename>
struct __is_void_helper
:public false_type{};
template<>
struct __is_void_helper<void>
:public true_type{};
template<typename T>
//最后繼承 false_type 或 true_type
struct is_void
:public __is_void_helper<typename remove_cv<T>::type>::type{};
運用到模板的特化解決問題龙致,很多思路都是可以借鑒的