C++ Type function(9)---《C++ Templates》

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。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值