[C++]模版特例化和模版偏特化

本文介绍了函数模板特例化及类模板偏特例化的概念,包括如何定义特例化版本,以及编译器如何选择合适的特例化版本进行匹配。同时,通过具体示例展示了不同特例化版本的应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

函数模版特例化

例子:

//第一个版本;可以比较任意两个类型
template<typename T> int compare(const &T,const T&);
//第二个版本处理字符串字面常量;重载实现
template<size_t N,size_t M>
int compare(const char(&)[N],const char (&)[M]);
//第三个版本;模版特例化
template<> int compare(const char*const &p1,const char*const &p2);

当定义函数模版的特例化版本时,我们本质上接管了编译器的工作。即,我们为原模版的一个特殊实例提供了定义。重要的是要弄清:一个特例化版本本质上是一个实例,而非函数名的一个重载版本

因此,如果我们使用了下面的调用:

compare("hi","tom");

使用两个函数模版都是可行的,且提供同样好的匹配。但是,接受字符数组参数的版本更特例化,因此编译器会选择它。

类模版偏特化

类模版部分特例化(partial specialization)
注意:我们只能部分特例化类模版,而不能部分特例化函数模版。

//原始的,最通用的版本
template<class T> struct remove_reference{
    typedef T type;
};
//部分特例化版本,将用于左值引用和右值引用
template<class T> struct remove_reference<T&>//左值引用
template<class T> struct remove_reference<T&>//右值引用
由于部分特例化版本本质是一个模版,所以我们首先定义模版参数。类似任何其他特例化版本,部分特例化版本的名字和原模版名字相同,对每个未完全确定类型的模版参数,在特例化版本的模版参数列表中都有一项与之对应。在类名后,我们要为特例化的模版参数指定实参,这些实参列于模版名之后的尖括号中,这些实参与原始模版中的参数按位置对应。
### C++11 中模板偏特化的用法及特性 #### 类模板全特 当定义了一个通用的类模板后,可以针对某些特定的数据类型提供专门版本的行为。这种机制被称为类模板的全特。 对于给定类型的每一个不同实例都可以拥有自己独特的成员变量初始方式以及成员函数逻辑。这允许程序员为不同的数据类型定制最优的操作流程[^1]。 考虑下面的例子: ```cpp #include <iostream> using namespace std; template<typename T> class Wrapper { public: T value; Wrapper(T v):value(v){} void showType(){ cout << "General Template" << endl; } }; // 完全特Wrapper<int> template<> class Wrapper<int> { private: int val; public: Wrapper(int v) :val(v){} void showType(){ cout << "Specialized for int" << endl; } void displayValue(){ cout << "Integer Value: " << this->val << endl; } }; ``` 在此案例中,`Wrapper<int>` 是 `Wrapper<T>` 的一个完全特版本,在处理整数时提供了额外的功能——打印具体的数值[^3]。 #### 函数模板 除了类之外,也可以对函数模板进行特。这意味着即使存在默认实现,编译器也会优先选用匹配度更高的重载形式或显式声明过的特例版函数[^4]。 示例如下: ```cpp #include <type_traits> template<typename T> void print(const T& t){ cout << "Generic version." << endl; } // 显式特print<const char*> template<> void print<const char*>(const char* s){ cout << "String literal specialization: "; while(*s != '\0'){ putchar(toupper(*s)); ++s; } cout << endl; } ``` 这里展示了如何创建一个用于字符串常量指针(`const char *`)的专用输出路径,它会把所有的字母转换成大写再显示出来[^2]。 #### 模板部分特 (Partial Specialization) 不同于上述两种情况,有时候并不希望覆盖整个模板定义而是仅改变其中一部分参数的表现形式;这时就可以利用到所谓的“部分特”。需要注意的是此功能只适用于类模板而非函数模板。 举个例子来说,假设有一个接受两个不同类型作为参数的容器适配器,并打算让其中一个位置固定为某个特定类别,则可以通过这种方式达成目标: ```cpp template<class T, class U=double> struct Holder{ T first; U second; }; // 部分特Holder以适应任意T但是U总是int的情况 template<class T> struct Holder<T,int>{ T item; static constexpr bool isInt=true; }; ``` 在这个片段里,如果第二个模板参数是指向整型的话那么就会触发这个特殊的结构体布局并设置静态成员标志位告知外界当前状态。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值