模板的特化
模板特化是C++中一种机制,允许为模板提供特定类型或特定值的定制实现。通常,模板是用于创建通用的数据类型或函数,但在某些情况下,我们可能希望为特定的类型或值提供特殊的实现。这就是模板特化发挥作用的地方。
有两种主要类型的模板特化:类模板特化和函数模板特化。
函数模板特化
/*************************************************************************
> File Name: test.cpp
> Author:Xiao Yuheng
> Mail:3312638794@qq.com
> Created Time: Sun Nov 12 20:48:52 2023
************************************************************************/
#include <iostream>
using namespace std;
template<typename T>
T add(T a, T b) {
return a + b;
}
template<>
int add<int>(int a, int b) {
cout << "int" << endl;
return a + b;
}
int main() {
cout << add(3, 4) << endl;
cout << add(3.1, 4.2) << endl;
return 0;
}
-
通用模板函数
add
:template<typename T> T add(T a, T b) { return a + b; }
这是一个通用的加法函数,用于接收两个相同类型的参数,并返回它们的和。
-
对
int
类型的特化:template<> int add<int>(int a, int b) { cout << "int" << endl; return a + b; }
这是
add
函数的特化版本,专门处理int
类型的参数。在特化版本中,你添加了输出语句以提示你正在使用特化版本。
我们来看看这段代码的输出结果:
可以发现当我们传入参数满足特化模板时,会优先调用特化模板。
类模板特化
/*************************************************************************
> File Name: test1.cpp
> Author:Xiao Yuheng
> Mail:3312638794@qq.com
> Created Time: Sun Nov 12 21:01:07 2023
************************************************************************/
#include <iostream>
using namespace std;
template<typename T, typename U>
class Test {
public:
Test() {
cout << "class Test<T, U> " << endl;
}
};
template<>
class Test<int, double> {
public:
Test() {
cout << "class Test<int, double> " << endl;
}
};
template<typename T>
class Test<int, T> {
public:
Test() {
cout << "class Test<int, T> " << endl;
}
};
int main() {
Test<double, int> a;
Test<int, double> b;
Test<int, string> c;
return 0;
}
在这个样例中我们有三种形式的模板,分别是正常的模板(template<typename T, typename U>
),全特化版本(template<>
),偏特化版本(template<typename T>
),我们来看看这个样例的输出有什么不一样:
-
我们可以发现第一个调用的是正常版本的模板
-
第二个既满足正常的模板,也满足全特化版本,还满足偏特化版本,可是这里调用的是全特化版本的模板,说明全特化模板的优先级最高
-
第三个既满足正常的模板,也满足偏特化版本,这里调用的是偏特化版本,说明偏特化版本的优先级比正常的模板高
优先级:全特化 > 偏特化 > 正常版本
我们来自己实现一个样例:
/*************************************************************************
> File Name: test.cpp
> Author:Xiao Yuheng
> Mail:3312638794@qq.com
> Created Time: Sun Nov 12 20:48:52 2023
************************************************************************/
#include <iostream>
using namespace std;
class A {};
class B {};
int main() {
cout << type_trais<int>::has_constructor << endl; // no
cout << type_trais<A>::has_constructor << endl; // yes
cout << type_trais<double>::has_constructor << endl; // no
cout << type_trais<B>::has_constructor << endl; // yes
cout << type_trais<string>::has_constructor << endl; // yes
cout << type_trais<string *>::has_constructor << endl; // no
return 0;
}
让这段主函数可以正常运行,且输出的结果是我们后面所标识的:
完整代码:
/*************************************************************************
> File Name: test.cpp
> Author:Xiao Yuheng
> Mail:3312638794@qq.com
> Created Time: Sun Nov 12 20:48:52 2023
************************************************************************/
#include <iostream>
using namespace std;
template<typename T>
class type_trais {
public:
static const char *has_constructor;
};
template<typename T>
const char *type_trais<T>::has_constructor = "yes";
template<typename T>
class type_trais<T *> {
public:
static const char *has_constructor;
};
template<typename T>
const char *type_trais<T *>::has_constructor = "no";
template<>
class type_trais<int> {
public:
static const char *has_constructor;
};
const char *type_trais<int>::has_constructor = "no";
template<>
class type_trais<double> {
public:
static const char *has_constructor;
};
const char *type_trais<double>::has_constructor = "no";
class A {};
class B {};
int main() {
cout << type_trais<int>::has_constructor << endl; // no
cout << type_trais<A>::has_constructor << endl; // yes
cout << type_trais<double>::has_constructor << endl; // no
cout << type_trais<B>::has_constructor << endl; // yes
cout << type_trais<string>::has_constructor << endl; // yes
cout << type_trais<string *>::has_constructor << endl; // no
return 0;
}
这段代码主要演示了C++中的模板特化,通过定义一个 type_traits
类模板,下面我将对代码进行详细解释:
-
type_trais
类模板的通用定义:template<typename T> class type_trais { public: static const char *has_constructor; }; template<typename T> const char *type_trais<T>::has_constructor = "yes";
-
type_trais
类模板的部分特化(指针类型):template<typename T> class type_trais<T *> { public: static const char *has_constructor; }; template<typename T> const char *type_trais<T *>::has_constructor = "no";
-
type_trais
类模板的完全特化(int 和 double 类型):template<> class type_trais<int> { public: static const char *has_constructor; }; const char *type_trais<int>::has_constructor = "no"; template<> class type_trais<double> { public: static const char *has_constructor; }; const char *type_trais<double>::has_constructor = "no";
-
在
main
函数中的测试:int main() { cout << type_trais<int>::has_constructor << endl; // 输出: no cout << type_trais<A>::has_constructor << endl; // 输出: yes cout << type_trais<double>::has_constructor << endl; // 输出: no cout << type_trais<B>::has_constructor << endl; // 输出: yes cout << type_trais<string>::has_constructor << endl; // 输出: yes cout << type_trais<string *>::has_constructor << endl; // 输出: no return 0; }
这样就可以实现我们主函数的所有功能。
简化版本
/*************************************************************************
> File Name: test.cpp
> Author:Xiao Yuheng
> Mail:3312638794@qq.com
> Created Time: Sun Nov 12 20:48:52 2023
************************************************************************/
#include <iostream>
using namespace std;
class yes_constructor {
public:
static const char *has_constructor;
};
const char *yes_constructor::has_constructor = "yes";
class no_constructor {
public:
static const char *has_constructor;
};
const char *no_constructor::has_constructor = "no";
template<typename T>
class type_trais : public yes_constructor {};
template<typename T>
class type_trais<T *> : public no_constructor {};
template<>
class type_trais<int> : public no_constructor {};
template<>
class type_trais<double> : public no_constructor {};
class A {};
class B {};
int main() {
cout << type_trais<int>::has_constructor << endl; // no
cout << type_trais<A>::has_constructor << endl; // yes
cout << type_trais<double>::has_constructor << endl; // no
cout << type_trais<B>::has_constructor << endl; // yes
cout << type_trais<string>::has_constructor << endl; // yes
cout << type_trais<string *>::has_constructor << endl; // no
return 0;
}
用继承简单简化一下。