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

来源:互联网 发布:中欧工程技术学院知乎 编辑:程序博客网 时间:2024/05/01 00:17

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。

原创粉丝点击