欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 社会 > C++ 语言特性30 - 模板介绍

C++ 语言特性30 - 模板介绍

2025/3/18 1:10:18 来源:https://blog.csdn.net/zg260/article/details/142717766  浏览:    关键词:C++ 语言特性30 - 模板介绍

目录

一:C++11 之前的模板特性

1. 函数模板:

2. 类模板:

3. 模板特化:

4. 模板参数:

5. 模板元编程:

二:C++11的模板特性 

1. 变长模板(Variadic Templates):

2. 右值引用和完美转发:

3. 类型别名模板(Type Alias Templates):

4.  decltype 关键字

5. 默认模板参数

6. 非类型模板参数

7. 模板特化

三:C++17的模板特性

1. 模板参数推导(Template Parameter Deduction for Class Templates)

2. std::optional

3. std::variant

4. if 和 switch 语句中的初始化(If and Switch with Initialization)

5. constexpr 增强

6. std::any

7.模板的 std::decay

四:C++20的模板特性

1. 概念(Concepts)

2. 模板参数的约束(Template Parameter Constraints)

3. 模板模板参数(Template Template Parameters):

 


一:C++11 之前的模板特性

  1. 函数模板

   允许定义可以接受不同类型参数的函数。函数模板在调用时根据参数类型进行实例化。

template<typename T>
T add(T a, T b) {return a + b;
}int main() {int result1 = add(3, 4);         // 实例化为 intdouble result2 = add(3.5, 2.5);  // 实例化为 double
}

 2. 类模板

  允许定义可以接受不同类型参数的类。类模板在创建对象时根据类型参数进行实例化。

template<typename T>
class Box {
public:Box(T value) : value(value) {}T getValue() { return value; }
private:T value;
};int main() {Box<int> intBox(10);      // 实例化为 Box<int>Box<std::string> strBox("Hello"); // 实例化为 Box<std::string>
}

3. 模板特化

 允许为特定类型提供不同的实现,称为模板特化。可以是完全特化或偏特化。

template<typename T>
class Box {
public:void print() { std::cout << "Generic Box" << std::endl; }
};// 完全特化
template<>
class Box<int> {
public:void print() { std::cout << "Integer Box" << std::endl; }
};int main() {Box<double> box1;box1.print(); // 输出 "Generic Box"Box<int> box2;box2.print(); // 输出 "Integer Box"
}

4. 模板参数

模板可以使用非类型参数,例如整数常量。

template<int size>
class Array {
public:int data[size]; // 使用非类型模板参数
};int main() {Array<10> arr; // 创建一个大小为 10 的数组
}

 5. 模板元编程

  在 C++11 之前,模板还可以用于编写编译时计算的元编程,例如计算阶乘、斐波那契数列等。

template<int N>
struct Factorial {static const int value = N * Factorial<N - 1>::value;
};template<>
struct Factorial<0> {static const int value = 1;
};int main() {int result = Factorial<5>::value; // result 为 120
}

二:C++11的模板特性 

1. 变长模板(Variadic Templates)

允许定义接受可变数量参数的模板,简化了如容器、函数等的模板定义。

#include <iostream>// 基础模板
template<typename T>
void print(T value) {std::cout << value << std::endl;
}// 变长模板
template<typename T, typename... Args>
void print(T first, Args... args) {std::cout << first << ", ";print(args...); // 递归调用
}int main() {print(1, 2.5, "Hello", 'A'); // 输出: 1, 2.5, Hello, A
}

 2. 右值引用和完美转发

引入了右值引用和 std::forward,使得模板能够更高效地处理不同类型的参数。

#include <iostream>
#include <utility>template<typename T>
void process(T&& arg) {// 处理 argstd::cout << arg << std::endl;
}template<typename T>
void wrapper(T&& arg) {process(std::forward<T>(arg)); // 完美转发
}int main() {int x = 10;wrapper(x); // 左值wrapper(20); // 右值
}

3. 类型别名模板(Type Alias Templates)

使用 using 定义类型别名模板,使得模板的可读性更强。

#include <iostream>
#include <vector>// 定义类型别名模板
template<typename T>
using Vec = std::vector<T>;int main() {Vec<int> intVec; // 实际上是 std::vector<int>intVec.push_back(1);std::cout << intVec[0] << std::endl; // 输出: 1
}

4.  decltype 关键字

decltype 关键字可以用于模板中,以便在编译时推导表达式的类型。

#include <iostream>template<typename T>
void displayType(T arg) {// 使用 decltype 获取类型decltype(arg) var = arg;std::cout << "Type of var: " << typeid(var).name() << std::endl;
}int main() {displayType(10);          // 输出: Type of var: intdisplayType(3.14);       // 输出: Type of var: double
}

5. 默认模板参数

C++11 允许为模板参数指定默认值,这样在某些情况下可以简化调用。

#include <iostream>template<typename T, int size = 10>
class Array {
public:T data[size]; // 使用默认模板参数void printSize() {std::cout << "Array size: " << size << std::endl;}
};int main() {Array<int> arr; // 使用默认参数arr.printSize(); // 输出: Array size: 10Array<double, 20> arr2; // 指定大小arr2.printSize(); // 输出: Array size: 20
}

6. 非类型模板参数

C++11 引入了更多类型的非类型模板参数,例如可以使用指针和引用作为模板参数。

#include <iostream>template<int N>
class Array {
public:int data[N]; // 使用非类型模板参数void printSize() {std::cout << "Array size: " << N << std::endl;}
};int main() {Array<5> arr; // 创建大小为 5 的数组arr.printSize(); // 输出: Array size: 5
}

7. 模板特化

在 C++11 中,你可以使用完全特化和部分特化来处理特定类型的情况。

#include <iostream>// 基础模板
template<typename T>
class Box {
public:void display() { std::cout << "Generic Box" << std::endl; }
};// 完全特化
template<>
class Box<int> {
public:void display() { std::cout << "Integer Box" << std::endl; }
};int main() {Box<double> box1;box1.display(); // 输出: Generic BoxBox<int> box2;box2.display(); // 输出: Integer Box
}

三:C++17的模板特性

1. 模板参数推导(Template Parameter Deduction for Class Templates)

C++17 允许在类模板中通过构造函数自动推导类型参数,从而简化模板的使用。

#include <iostream>template<typename T>
class Wrapper {
public:Wrapper(T value) : value(value) {}T getValue() const { return value; }
private:T value;
};int main() {Wrapper w(42); // T 被推导为 intstd::cout << w.getValue() << std::endl; // 输出: 42Wrapper<double> w2(3.14); // 显式指定类型std::cout << w2.getValue() << std::endl; // 输出: 3.14
}

2. std::optional

C++17 引入了 std::optional,用于表示可能没有值的情况,结合模板使用时非常方便。

#include <iostream>
#include <optional>std::optional<int> findValue(bool exists) {if (exists) return 42;return std::nullopt; // 表示无值
}int main() {auto value = findValue(true);if (value) {std::cout << *value << std::endl; // 输出: 42} else {std::cout << "No value found" << std::endl;}auto noValue = findValue(false);if (!noValue) {std::cout << "No value found" << std::endl; // 输出: No value found}
}

3. std::variant

std::variant 是 C++17 引入的一个类型安全的联合体,允许多个类型的值共存。

#include <iostream>
#include <variant>std::variant<int, double, std::string> getValue(bool flag) {if (flag) return 10;return 3.14; // 返回 double
}int main() {auto value = getValue(true);// 使用 std::visit 处理 variantstd::visit([](auto&& arg) {std::cout << arg << std::endl; // 输出: 10}, value);value = getValue(false);std::visit([](auto&& arg) {std::cout << arg << std::endl; // 输出: 3.14}, value);
}

4. ifswitch 语句中的初始化(If and Switch with Initialization)

C++17 允许在 ifswitch 语句中直接进行初始化,增强了代码的简洁性。

#include <iostream>bool checkValue() {return true;
}int main() {// 在 if 语句中初始化if (auto value = checkValue()) {std::cout << "Value is true" << std::endl;} else {std::cout << "Value is false" << std::endl;}
}

5. constexpr 增强

C++17 扩展了 constexpr 的功能,使得模板可以在编译时进行更多计算。

#include <iostream>constexpr int factorial(int n) {return n <= 1 ? 1 : n * factorial(n - 1);
}int main() {constexpr int value = factorial(5); // 在编译时计算std::cout << "Factorial of 5: " << value << std::endl; // 输出: Factorial of 5: 120
}

6. std::any

std::any 是 C++17 引入的另一种类型安全的容器,允许存储任意类型的值。

#include <iostream>
#include <any>int main() {std::any anyValue = 10; // 存储整数std::cout << std::any_cast<int>(anyValue) << std::endl; // 输出: 10anyValue = std::string("Hello, World!"); // 存储字符串std::cout << std::any_cast<std::string>(anyValue) << std::endl; // 输出: Hello, World!
}

7.模板的 std::decay

C++17 引入了 std::decay,用于获取参数类型的“衰变”类型,常用于模板中。

#include <iostream>
#include <type_traits>template<typename T>
void printType(T&& arg) {using DecayedType = typename std::decay<T>::type;std::cout << "Type: " << typeid(DecayedType).name() << std::endl;
}int main() {int x = 10;printType(x); // 输出类型为 intprintType(20); // 输出类型为 intprintType("Hello"); // 输出类型为 const char*
}

四:C++20的模板特性

1. 概念(Concepts)

概念用于定义模板参数的约束条件,使得模板编程更加类型安全和可读。

#include <iostream>
#include <concepts>// 定义一个概念:必须是可加的类型
template<typename T>
concept Addable = requires(T a, T b) {{ a + b } -> std::same_as<T>;
};template<Addable T>
T add(T a, T b) {return a + b;
}int main() {std::cout << add(5, 10) << std::endl; // 输出: 15// std::cout << add(5.5, 2.5) << std::endl; // 正确,输出: 8.0// std::cout << add("Hello", "World"); // 错误,类型不满足 Addable 概念
}

2. 模板参数的约束(Template Parameter Constraints)

C++20 允许在模板定义中直接使用概念作为参数约束,增加了代码的可读性和类型安全。

#include <iostream>
#include <concepts>template<typename T>
void process(T value) requires std::integral<T> {std::cout << "Processing integral value: " << value << std::endl;
}int main() {process(10); // 正确// process(3.14); // 错误,double 不是整数
}

3. 模板模板参数(Template Template Parameters)

增强了对模板模板参数的支持,可以更灵活地处理各种模板结构。

template<template<typename> class Container, typename T>
void process(Container<T> c) {// 处理容器
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词