欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C++中的特化问题和类型萃取问题

程序员文章站 2022-06-10 14:38:31
...

模板的特化

概念

 从字面上来解释,就是为已有的模板参数进行一些使其特殊化的指定,使得以前不受任何约束的模板参数,或受到特定的修饰(例如const或者摇身一变成为了指针,甚至是经过别的模板类包装之后的模板类型)或完全被指定了下来。

全特化:

就是模板中模板参数全被指定为确定的类型。全特化也就是定义了一个全新的类型,全特化的类中的函数可以与模板类不一样。

偏特化:

就是模板中的模板参数没有被全部确定,需要编译器在编译时进行确定。

全特化的标志就是产生出完全确定的东西,而不是还需要在编译期间去搜寻适合的特化实现

模板类全特化

template <class T1,class T2>
class KeyVal
{
protected:
    T1 _key;
    T2 _val;
};

//全特化
template<> 
class KeyVal<int,char>
{
protected:
    int _key;
    char _val;
};

这里归纳下针对类模板特化的几种类型

  • 一是特化为绝对类型;
  • 二是特化为引用,指针类型;
  • 三是特化为另外一个类模板。

模板类的偏特化

template <class T1,class T2>
class KeyVal
{
protected:
    T1 _key;
    T2 _val;
};

template<class T2>  //局部特化
class KeyVal<int,T2>
{
protected:
    int _key;
    T2 _val;
};

template <class T1,class T2> //局部特化
class KeyVal<T1*,T2*>
{
protected:
    T1 _key;
    T2 _val;
};

从上面的例子可以看出局部特化偏特化并不仅仅是指特化部分参数,而是针对模板参数更进一步的条件限制所设计出来的一个特化版本。

模板函数全特化

template <class T>
void Display(const T& x)
{
    cout<<x<<endl;
}


template <>//模板函数全特化
void Display(const int& x)
{
    cout<<x<<endl;
}

全局函数模板特化不能包含缺省的实参值。然而,对于基本(即要被特化的)模板所指定的任何缺省实参,显式特化版本都可以应用这些缺省实参值。

模板函数不支持局部特化。

全局特化和局部特化都没有引入一个全新的模板或者模板实例。它们只是对原来的泛型(或者非特化)模板中已经隐式声明的实例提供另一种定义。在概念上,这是一个相对比较重要的现象,也是特化区别于重载模板的关键之处。

类型萃取

当我们在写Vector和List的时候,遇到了这样的问题,在拷贝构造函数中和顺序表扩容时,当是内置类型我们可以直接使用memcpy把旧空间的内容考到新空间,但是当遇到strring类型时使用memcpy就会发生浅拷贝问题,会造成对一块空间同时析构多次。当时为了解决这个问题就统一使用了深拷贝。显然这样的解决方法不是最优的。如果我们可以确定类型,当是内置类型时就用memcpy,遇到string类型时就是用深拷贝。

类型萃取代码实现

struct __TrueType
{};

struct __FalseType 
{};

template<class T>
struct TypeTraits
{
    typedef __FalseType IsPodType;
};

template<class T>
T* __TypeCopy(const T* src,T* dst,size_t n,__TrueType)
{
    cout<<"memcpy"<<endl;
    return (T*)memcpy(dst,src,n*sizeof(T));
}

template<class T>
T* __TypeCopy(const T* src,T* dst,size_t n,__FalseType)
{
    cout<<"for+operator= "<<endl;
    for (size_t i=0; i<n; i++)
    {
        dst[i] = src[i];
    }
    return dst;
}

template<class T>
T* TypeCopy(const T* src,T* dst,size_t n)
{
    return __TypeCopy(src,dst,n,TypeTraits<T>::IsPodType());
}


template<>
struct TypeTraits<int>
{
    typedef __TrueType IsPodType;
};
template<>
struct TypeTraits<char>
{
    typedef __TrueType IsPodType;
};
template<>
struct TypeTraits<double>
{
    typedef __TrueType IsPodType;
};
template<>
struct TypeTraits<float>
{
    typedef __TrueType IsPodType;
};

测试代码:

void TestType()
{
    int srcint[5]={1,2,3,4,5};
    int dstint[5];

    string srcstr[3]={"11","22","33"};
    string dststr[3]={};

    TypeCopy(srcint,dstint,5);
    TypeCopy(srcstr,dststr,3);

}

测试结果:
C++中的特化问题和类型萃取问题