【类模板】类模板的特化

一、类模板的泛化

与函数模板一样,类模板的泛化就是普通的模板,不具有特殊性的模板。
以下的类模板为泛化的版本

//类模板的泛化
template<typename T,typename U>
struct TC {

    //静态成员变量
    static int static_varible;  //声明

    TC() {
        std::cout << "TC泛化版本的构造函数\n";
    }

    void func1(); 

    void func2();
};

//类外实现func1
template<typename T,typename U>
void TC<T, U>::func1() {
    std::cout << "func1的泛化版本\n";
}

//类外实现func2
template<typename T, typename U>
void TC<T, U>::func2() {
    std::cout << "func2的泛化版本\n";
}

template<typename T,typename U>
int TC<T, U>::static_varible = 50; //定义(初始化)

这里采用的类内声明,类外定义的方法

二、类模板的全特化

1.类模板的全特化

我们可以在有泛化版本的前提下,加入一个全特化的版本,如下所示:

//类模板的全特化
template<>
struct TC<int,int> { //<>符号是必要的
    TC() {
        std::cout << "TC<int,int>的特化版本构造函数\n";
    }

    void func1() {
        std::cout << "TC<int,int>的特化版本func1函数\n";
    }

    void func2();

    //添加泛化版本中没有的函数
    void func3();
};

注意,我们在类外实现函数的时候不能加入 t e m p l a t e < > template<> template<>,否则会编译失败。

//类外实现func2
//注意全特化版本类外实现不能加template<>

//template<>
void TC<int, int>::func2() {
    std::cout << "TC<int,int>的特化版本func2函数\n";

}

//类外实现fun3
void TC<int, int>::func3() {
    std::cout << "TC<int,int>的特化版本func3函数\n";
}

由于全特化版本的类已经和泛化版本的类区分开来了,因此可以添加上泛化版本没有的内容。
如我们在成员函数上增加了 f u n c 3 func3 func3函数。

2. 普通成员函数的全特化

我们这里以全特化 f u n c 1 func1 func1函数为例:

//普通成员函数的全特化
template<> //这里可加可不加
void TC<double, int>::func1() { //全特化func1成员函数
    std::cout << "普通成员函数TC<double,int>::func1的全特化\n";
};

成员函数的全特化可以忽略 t e m p l a t e < > template<> template<>,也可以使用。

注意,如果我们先对泛化版本添加了成员函数的全特化版本,那么我们就无法对泛化版本添加相同的全特化的类模板,因为类模板的成员函数已经被占用了。

如图:

template<> 
struct TC<double,int> { //此时TC的<double,int>版本部分内容已经被占用了
    TC();
    
    void func1();

    void func2();

};

会编译失败
在这里插入图片描述

3.静态成员变量的全特化

对于静态成员函数的全特化,我们首先必须在类外定义静态成员函数的泛化版本,然后再加入全特化版本。

泛化版本的定义:

template<typename T,typename U>
int TC<T, U>::static_varible = 50; //定义(初始化)

加入全特化版本的静态成员变量:

//静态成员变量的全特化
template<> //这里可加可不加
int TC<double, int>::static_varible = 100; 

对于静态成员变量的全特化,与普通成员函数一样,已经占有了就不能再加入相同版本的全特化类模板了。

三、类模板的偏特化

函数模板不具有偏特化,而类模板可以进行偏特化。

1. 模板参数数量上的偏特化

我们可以指定类模板的某些参数类型,特殊对其进行偏特化:
下面是 T C TC TC类模板在参数数量上的偏特化版本:

//模板参数数量上的偏特化
template<typename U>
struct TC<float, U> {
    TC() {
        std::cout << "TC<float,U>偏特化版本的构造函数\n";
    }

    void fun1();
};
//类外实现
template<typename U>
void TC<float, U>::fun1() {
    std::cout << "TC<float,U>偏特化版本的func1函数\n";
}


通过调用,我们发现使用了偏特化版本

void Test() {
    TC<float,int>t;
}

如图所示:

在这里插入图片描述

2.模板参数范围上的偏特化

有时,对于一些特殊的类型参数我们要进行特殊处理,如
∗ ( 指针 ) , & ( 左值引用 ) , & & ( 右值引用 ) , c o n s t ( 常变量 ) *(指针),\&(左值引用),\&\&(右值引用),const(常变量) (指针),&(左值引用),&&(右值引用),const(常变量)
因此,我们就可以对这些变量加入偏特化版本:
下面实现一个偏特化的 T C < c o n s t   T , U ∗ > TC<const \ T,U*> TC<const T,U>的版本:

//模板参数范围上的偏特化
template<typename T,typename U>
struct TC<const T, U*> { //限定T为const类型,U为指针
    TC() {
        std::cout << "TC<const T,U*>偏特化版本的构造函数\n";
    }
    void func1();
};

//类外实现
template<typename T,typename U>
void TC<const T, U*>::func1() {
    std::cout << "TC<const T,U*>偏特化版本的func1函数\n";
}

而这样就能缩小范围,在调用时优先调用偏特化版本。
如下图所示:
:
优先使用了偏特化版本的构造函数。

当然,如果去掉了这个偏特化版本,将会调用泛化版本。

注释掉偏特化版本后,运行得到:

在这里插入图片描述
由于找不到全特化版本和偏特化版本,因此最终调用了泛化版本

3.其他

最后,对于偏特化版本的话,不存在对成员函数或静态成员变量的偏特化。
以下代码无法通过编译:

//不存在对成员函数的偏特化
template<typename U>
void TC<double, U>::func2() {
    std::cout << "TC<double,U>偏特化版本的func2函数\n";
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值