C++ STL系列-02.泛型入门
C++中的泛型编程主要通过模板(template)实现。模板允许我们编写与类型无关的代码,是一种将类型作为参数进行编程的方式。在C++中,模板分为函数模板和类模板。
1. 函数模板
函数模板允许我们定义一个函数,它可以接受多种类型的参数。例如,我们可以写一个比较两个值大小的函数模板,而不是为每种类型都写一个重载函数。
#include<iostream>
template<typename T>
T max(T a, T b) {
return a > b ? a : b;
}
int main(int argc, char*argv[]) {
int a = 1, b = 5;
std::cout << max(a, b) << std::endl;
char c = 'a', d = 'h';
std::cout << max(c, d) << std::endl;
return 0;
}
在上面的代码中,template 告诉编译器这是一个模板,T 是一个占位符类型。当我们调用 max 函数时,编译器会根据传入的参数类型自动生成特定类型的函数。
2. 类模板
类模板允许我们定义一个类,其成员的类型可以由模板参数指定。例如,我们可以定义一个简单的Box类,用来存储任意类型的值。
#include<iostream>
template<typename T>
class Box {
private:
T content;
public:
Box(T value) : content(value) {} // 赋值给 content
T getValue() {
return content;
}
};
//使用类模板时,我们需要在创建对象时指定类型:
int main(int argc, char*argv[]) {
Box<int>a = 1;
Box<std::string>b("hello");
std::cout << a.getValue() << std::endl;
std::cout << b.getValue() << std::endl;
return 0;
}
3.可变参数模板
C++11引入了可变参数模板,允许模板接受可变数量的参数。例如,我们可以定义一个函数,它可以接受任意数量的参数并打印它们:
#include<iostream>
// 基本可变参数模板示例:打印所有参数
// 递归终止函数
void print() {
std::cout << std::endl;
}
// 递归展开参数包
template<typename T, typename... Args>
void print(T first, Args... args) {
std::cout << first << " ";
print(args...);
}
int main(int argc, char*argv[]) {
print(1,2,'g',"hello");
return 0;
}
C++17引入了折叠表达式,可以更简洁地展开参数包。
#include<iostream>
template<typename... Args>
void print(Args... args) {
(std::cout << ... << args) << std::endl;
}
int main(int argc, char*argv[]) {
print(1,2,'g',"hello");
return 0;
}
使用折叠表达式求和
#include<iostream>
template<typename... Args>
auto sum(Args... args) {
return (args + ...);
}
int main(int argc, char*argv[]) {
std::cout << sum(1,2,3,4,5) << std::endl;
return 0;
}
使用折叠表达式遍历加空格
#include<iostream>
template<typename ...Args>
void print(Args... args) {
((std::cout << args << ' '), ...) << std::endl;
}
int main(int argc, char*argv[]) {
print(1,2,3,4,5);
return 0;
}
将参数包存入vector
#include<iostream>
#include<vector>
template<typename T, typename... Args>
std::vector<T> make_vector(Args... args) {
return std::vector<T>{static_cast<T>(args)...};
}
int main(int argc, char*argv[]) {
auto vec = make_vector<int>(1, 2, 3, 4, 5);
std::cout << "Vector: ";
for (auto v : vec) {
std::cout << v << " ";
}
return 0;
}