模板
C++的泛型特性需要使用模板(Templates)。使用模板可以让函数或类在编译时自动适应不同的数据类型。我认为C++的泛型特性和Rust的是非常相似的,这里在介绍C++模板的同时,和Rust的泛型机制进行比较。
这是使用C++和Rust分别实现通用max
函数的例子。一个显著的区别是C++没有对类型的约束,而Rust通过trait来约束泛型,这类似于C++中的接口(interfaces)或抽象基类,但更灵活。
类型约束
C++20引入了concept
的概念,这个概念类似Rust中的trait。可以利用它来约束泛型的参数类型了。在C++20中,max
函数的写法最好改成:
#include <concepts>
template <typename T>
requires std::totally_ordered<T> // NOTICE
T max(T a, T b) { return a > b ? a : b; }
当然,由于模板是在编译时特化的。所以即使不加这行requires
,使用模板实例化无法比较的类型还是会报错,只是报错信息可能就不那么友好了。另外,由于没有约束,可能会出现模板可以通过编译但是语义不正确的情况,要额外小心。
特化
模板特化是一个非常强大的特性,它允许开发者为模板提供特定类型的特殊实现。这包括全特化(Full Specialization)和偏特化(Partial Specialization)。这两种特化方式允许针对特定的类型或类型组合提供优化或特殊行为的模板代码。简单的说,就是为泛型参数T
的某个具体的类型单独实现一套代码。当模板参数的类型完全匹配这个特化定义时,编译器会使用这个特化的实现而不是通用模板。
一个典型的例子是STL中的std::vector<T>
和std::vector<bool
。
Rust的特化在积极的开发中,具体进度可以参考RFC1210。