C和C++中,大部分functions可以被称之为value functions,它们接受某些values作为自变量并传回一个value作为结果。现在我们运用templates技术实作出所谓的type functions:接受一个types作为自变量,并产生一个type或constant作为结果。
zizeof就是一个非常有用的type function,其中class templates可以充当type function,此时参数就是template parameters,结果被萃取为一个member type或者member constant。
#include <stddef.h》
#include <iostream>
template <typename T>
class TypeSize{
public:
static size_t const value=sizeof(T);
};
int main(){
std::cout<<"TypeSize<int>::value="<<TypeSize<int>::value<<std::endl;
return 0;
}
决定元素类型
我们有多个container templates,我们希望有个type function,在接受一个container type之后可以输出element type(元素类型),这可以通过偏特化达成。
#include <vector>
#include <list>
#include <stack>
#include <iostream>
#include <typeinfo>
template <typename T>
class ElementsT;
template <typename T>
class ElementT<std::vector<T> >{
public:
typedef T Type;
};
template <typename T>
class ElementT<std::list<T> >{
public:
typedef T Type;
};
template <typename T>
class ElementT<std::stack<T> >{
public:
typedef T Type;
};
template <typename T>
void print_element_type(T const& c){
std::cout<<"Container of "<<typeid(typename ElementT<T>::Type).name()<<" elements.\n";
}
int main(){
std::stack<bool> s;
print_element_type(s);
}
上面我们通过偏特化实现了这项功能而无需要求container types必须对type function了解。然而在很多场合中,type function往往和可施行于其上的types一块设计,让实作码更易简化:
template <typename C>
class ElementT{
public:
typedef typename C::value_type Type;
};
type function的价值如何体现呢?它允许我们以container type来得以参数化某个template,而且并不要求必须一并提供element type的相关参数 及其他特征。
template <typename T,typename C>
T sum_of_element(C const&c);
如果我们类似上面这样写的话,就需要以sum_of_elements<int>(list)之类的语法来明确指定element type。我们可以改而这样声明:
template <typename C>
typename ElementT<C>::Type sum_of_elements(C const& c);
这样的话,element type就可以有type function来指定了。
确认是否为Class Types
template <typename T>
class IsClassT{
private:
typedef char One;
typedef struct{char a[2];} Two;
template<typename C> static One test(int C::*);
template<typename C> static Two test(...);
public:
enum{Yes=sizeof(IsClassT<T>::test<T>(0))==1};
enum{No!=Yes};
};
template <typename T>
void check(){
if(IsClass<T>::Yes{
std::cout<<"IsClassT "<<std::endl;
}else{
std::cout<<"!IsClassT "<<std::endl;
}
}
References(引用)和Qualifiers(饰词)
template <typename T>
void apply(T& arg,void(*func)(T)){
func(arg);
}
#include <iostream>
void incr(int& a){
++a;
}
void print(int a){
std::cout<<a<<std::endl;
}
int main(){
int x=7;
apply(x,print);
apply(x,incr);
}
对于第一个函数调用没有任何问题,对于第二个呢?即调用apply(x,incr)时,T必须被替换为int&,这意味着第一个参数的类型必须是int&&,这并不是个合法的C++ type,所以后来的一份技术勘误提出:T&中的T如果被替换为int&,那么T&等价于int&。
template <typename T>
class TypeOp{
public:
typedef T ArgT;
typedef T BareT;
typedef T const ConstT;
typdedef T& RefT;
typedef T& RefBareT;
typedef T const& RefConstT;
};
template <typename T>
class TypeOp<T const>//偏特化版本
{
public:
typdef T const ArgT;
typedef T BareT;
typedef T const ConstT;
typedef T const& RefT;
typedef T& RefBareT;
typedef T const& RefConstT;
};
template <typename T>
class TypeOp<T&>{//针对references而设计的偏特化
public:
typedef T& ArgT;
typedef typename TypeOp<T>::BareT BareT;
typedef T const constT;
typedef T& RefT;
typedef typename TypeOp<T>::BareT& RefBareT;
typedef T const& RefConstT;
};
template<>
class TypeOp<void>{
public:
typedef void ArgT;
typedef void BareT;
typedef void const ConstT;
typedef void RefT;
typedef void RefBareT;
typedef void RefConstT;
};
template <typename T>
void apply(typename TypeOp<T>::RefT arg,void(*func)(T)){
func(arg);
}
Promotion Traits(类型晋升之特征萃取)
template <typename T>
Array<T> operator+(Array<T> const&,Array<T> const&);
然而现在我们想要将char类型和int类型的两个Array进行相加运算,这时候我们就需要决定返回值类型是什么东东?
template <typename T1,typename T2>
Array<???> operator+(Array<T> const&,Array<T2> const&);
我们怎样解决上面template function中的???呢?利用Promotion traits template就可以解决:
template <typename T1,typename T2>
Array<typename Promotion<T1,T2::ResultT> operator+ (Array<T1> const&,Array<T2> const&);
template <typename T1,typename T2>
typename Promotion<Array<T1>,Array<T2> >::Result operator+ (Array<T1> const&,Array<T2> const&);
template <bool c,typename Ta,typename Tb>
class IfThenElse;
template <typename Ta,typename Tb>
class IfThenElse<true,Ta,Tb>{
public:
typedef Ta ResultT;
}
template <typename Ta,typename Tb>
class IfThenElse<false,Ta,Tb>{
public:
typedef Tb ResultT;
};
template <typename T1,typename T2>
class Promotion{
public:
typedef typename IfThenElse<(sizeof(T1)>sizeof(T2)),T1,typename IfThenElse<(sizeof(T1)<sizeof(T2)),T2,void>::ResultT>::ResultT ResultT;
};
//偏特化版本
template <typename T1,typename T2>
class Promotion<Array<T1>,Array<T2> >{
public:
typedef Array<typename Promotion<T1,T2>::ResultT> ResultT;
};
template <typename T>
class Promotion<Array<T>,Array<T> >{
public:
typedef Array<typename Promotion<T,T>::ResultT> ResultT;
};
template <typename T>
class Promotion<T,T>{
public:
typedef T ResultT;
};
PS:
我们所给的traits templates实例都用以决定template parameters的属性,在混合类型操作中应该被提升为哪一种type?这样的traits被称为property traits。另外一些traits负责定义某些types如何被初值,我们称之为policy traits。