当前位置:首页 > > 充电吧
[导读]模版与特化的概念函数模版与类模版C++中模板分为函数模板和类模板函数模板:是一种抽象函数定义,它代表一类同构函数。类模板:是一种更高层次的抽象的类定义。特化的概念所谓特化,就是将泛型的东东搞得具体化一

模版与特化的概念


函数模版与类模版


C++中模板分为函数模板和类模板

函数模板:是一种抽象函数定义,它代表一类同构函数。

类模板:是一种更高层次的抽象的类定义。

特化的概念


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

模板特化的分类


针对特化的对象不同,分为两类:函数模板的特化和类模板的特化

函数模板的特化

当函数模板需要对某些类型进行特化处理,称为函数模板的特化。

类模板的特化

当类模板内需要对某些类型进行特别处理时,使用类模板的特化。

特化整体上分为全特化和偏特化 
* 全特化

就是模板中模板参数全被指定为确定的类型。

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

1234

偏特化

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

全特化的标志就是产生出完全确定的东西,而不是还需要在编译期间去搜寻适合的特化实现,貌似在我的这种理解下,全特化的 东西不论是类还是函数都有这样的特点,

模板函数只能全特化,没有偏特化(以后可能有)。

模板类是可以全特化和偏特化的。

template <>然后是完全和模板类型没有一点关系的类实现或者函数定义,如果你要说,都完全确定下来了,那还搞什么模板呀,直接定义不就完事了?

但是很多时候,我们既需要一个模板能应对各种情形,又需要它对于某个特定的类型(比如bool)有着特别的处理,这种情形下特化就是需要的了。

全特化的标志:template <>然后是完全和模板类型没有一点关系的类实现或者函数定义偏特化的标志:template函数模版特化


目前的标准中,模板函数只能全特化,没有偏特化

至于为什么函数不能偏特化,似乎不是因为语言实现不了,而是因为偏特化的功能可以通过函数的重载完成。

函数模版的特化技巧


函数模板的特化:当函数模板需要对某些类型进行特别处理,称为函数模板的特化。

例如,我们编写了一个泛化的比较程序

templateint compare(const T &left, const T&right)
{
    std::cout <<"in template..." <<std::endl;
    return (left - right);
}

123456

这个函数满足我们的需求了么,显然不,它支持常见int, float等类型的数据的比较,但是不支持char*(string)类型。

所以我们必须对其进行特化,以让它支持两个字符串的比较,因此我们实现了如下的特化函数。

template < >
int compare(const char* left, const char* right)
{
    std::cout <<"in special template< >..." <<std::endl;

    return strcmp(left, right);
}

1234567

也可以

template < >
int compare(const char* left, const char* right)
{
    std::cout <<"in special template< >..." <<std::endl;

    return strcmp(left, right);
}

1234567示例程序1–比较两个数据


#include#include///  模版特化

templateint compare(const T left, const T right)
{
    std::cout <<"in template..." <<std::endl;
    return (left - right);
}


//  这个是一个特化的函数模版
template < >int compare(const char* left, const char* right)
{
    std::cout <<"in special template< >..." <<std::endl;

    return strcmp(left, right);
}
//  特化的函数模版, 两个特化的模版本质相同, 因此编译器会报错
// error: redefinition of 'int compare(T, T) [with T = const char*]'|
//template < >//int compare(const char* left, const char* right)
//{
//    std::cout <<"in special template< >..." <<std::endl;
//
//    return strcmp(left, right);
//}


//  这个其实本质是函数重载
int compare(char* left, char* right)
{
    std::cout <<"in overload function..." <<std::endl;

    return strcmp(left, right);
}

int main( )
{
    compare(1, 4);

    const char *left = "gatieme";
    const char *right = "jeancheng";
    compare(left, right);

    return 0;
}

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051

函数模版的特化,当函数调用发现有特化后的匹配函数时,会优先调用特化的函数,而不再通过函数模版来进行实例化。

示例程序二-判断两个数据是否相等

#include#includeusing namespace std;
//函数模板
templatebool IsEqual(T t1,T t2){
    return t1==t2;
}

template<> //函数模板特化
bool IsEqual(char *t1,char *t2){
    return strcmp(t1,t2)==0;
}

int main(int argc, char* argv[])
{
    char str1[]="abc";
    char str2[]="abc";
    cout<<"函数模板和函数模板特化"<<endl;
    cout<<IsEqual(1,1)<<endl;
    cout<<IsEqual(str1,str2)<<endl;

    return 0;
}

1234567891011121314151617181920212223242526类模版特化


类模板的特化:与函数模板类似,当类模板内需要对某些类型进行特别处理时,使用类模板的特化。例如:

这里归纳了针对一个模板参数的类模板特化的几种类型

一是特化为绝对类型;

二是特化为引用,指针类型;

三是特化为另外一个类模板。

这里用一个简单的例子来说明这三种情况:

特化为绝对类型


也就是说直接为某个特定类型做特化,这是我们最常见的一种特化方式, 如特化为float, double等

#include#include#include// general version
templateclass Compare
{
public:
    static bool IsEqual(const T& lh, const T& rh)
    {
        std::cout <<"in the general class..." <<std::endl;
        return lh == rh;
    }
};



// specialize for float
template<>class Compare{
public:
    static bool IsEqual(const float& lh, const float& rh)
    {
        std::cout <<"in the float special class..." <<std::endl;

        return std::abs(lh - rh) < 10e-3;
    }
};

// specialize for double
template<>class Compare{
public:
    static bool IsEqual(const double& lh, const double& rh)
    {
        std::cout <<"in the double special class..." <<std::endl;

        return std::abs(lh - rh) < 10e-6;
    }
};


int main(void)
{
    Comparecomp1;
    std::cout <<comp1.IsEqual(3, 4) <<std::endl;
    std::cout <<comp1.IsEqual(3, 3) <<std::endl;

    Comparecomp2;
    std::cout <<comp2.IsEqual(3.14, 4.14) <<std::endl;
    std::cout <<comp2.IsEqual(3, 3) <<std::endl;

    Comparecomp3;
    std::cout <<comp3.IsEqual(3.14159, 4.14159) <<std::endl;
    std::cout <<comp3.IsEqual(3.14159, 3.14159) <<std::endl;
    return 0;
}

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859

如果期望使用偏特化,那么

templateclass A
{
}

templateclass A{
}

123456789特化为引用,指针类型


templatestruct iterator_traits {
  typedef typename _Iterator::iterator_category iterator_category;
  typedef typename _Iterator::value_type        value_type;
  typedef typename _Iterator::difference_type   difference_type;
  typedef typename _Iterator::pointer           pointer;
  typedef typename _Iterator::reference         reference;
};

// specialize for _Tp*
templatestruct iterator_traits{
  typedef random_access_iterator_tag iterator_category;
  typedef _Tp                         value_type;
  typedef ptrdiff_t                   difference_type;
  typedef _Tp*                        pointer;
  typedef _Tp&                        reference;
};

// specialize for const _Tp*
templatestruct iterator_traits{
  typedef random_access_iterator_tag iterator_category;
  typedef _Tp                         value_type;
  typedef ptrdiff_t                   difference_type;
  typedef const _Tp*                  pointer;
  typedef const _Tp&                  reference;
};

12345678910111213141516171819202122232425262728

当然,除了T*, 我们也可以将T特化为 const T*, T&, const T&等,以下还是以T*为例:

// specialize for T*
templateclass Compare{
public:
    static bool IsEqual(const T* lh, const T* rh)
    {
        return Compare::IsEqual(*lh, *rh);
    }
};

12345678910

这种特化其实是就不是一种绝对的特化, 它只是对类型做了某些限定,但仍然保留了其一定的模板性,这种特化给我们提供了极大的方便, 如这里, 我们就不需要对int*, float*, double*等等类型分别做特化了。

这其实是第二种方式的扩展,其实也是对类型做了某种限定,而不是绝对化为某个具体类型,如下:

// specialize for vectortemplateclass Compare<vector>
{
public:
    static bool IsEqual(const vector& lh, const vector& rh)
    {
        if(lh.size() != rh.size()) return false;
        else
        {
            for(int i = 0; i < lh.size(); ++i)
            {
                if(lh[i] != rh[i]) return false;
            }
        }
        return true;
    }
};

123456789101112131415161718

这就把IsEqual的参数限定为一种vector类型, 但具体是vector还是vector, 我们可以不关心, 因为对于这两种类型,我们的处理方式是一样的,我们可以把这种方式称为“半特化”。

当然, 我们可以将其“半特化”为任何我们自定义的模板类类型:

// specialize for any template class type
templatestruct SpecializedType
{
    T1 x1;
    T1 x2;
};
templateclass Compare<SpecializedType>
{
public:
    static bool IsEqual(const SpecializedType& lh, const SpecializedType& rh)
    {
        return Compare::IsEqual(lh.x1 + lh.x2, rh.x1 + rh.x2);
    }
};

12345678910111213141516

这就是三种类型的模板特化, 我们可以这么使用这个Compare类:

   // int
    int i1 = 10;
    int i2 = 10;
    bool r1 = Compare::IsEqual(i1, i2);

    // float
    float f1 = 10;
    float f2 = 10;
    bool r2 = Compare::IsEqual(f1, f2);

    // double
    double d1 = 10;
    double d2 = 10;
    bool r3 = Compare::IsEqual(d1, d2);

    // pointer
    int* p1 = &i1;
    int* p2 = &i2;
    bool r4 = Compare::IsEqual(p1, p2);

    // vectorvectorv1;
    v1.push_back(1);
    v1.push_back(2);

    vectorv2;
    v2.push_back(1);
    v2.push_back(2);
    bool r5 = Compare<vector>::IsEqual(v1, v2);

    // custom template class 
    SpecializedTypes1 = {10.1f,10.2f};
    SpecializedTypes2 = {10.3f,10.0f};
    bool r6 = Compare<SpecializedType>::IsEqual(s1, s2);


本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭