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

模板的特化

概念

 从字面上来解释,就是为已有的模板参数进行一些使其特殊化的指定,使得以前不受任何约束的模板参数,或受到特定的修饰(例如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);

}

测试结果:
这里写图片描述

猜你喜欢

转载自blog.csdn.net/qq_38646470/article/details/80303575