C++ Traits技术
2023-12-18 21:58:10 # 技术

概述

在 C++中,「traits」(特性,又被叫做特性萃取技术)是一种元编程技术,通过定义模板类或模板函数来描述类型的特性和属性。这些特性可以是类型的一些基本信息。
Traits 技术在 C++中广泛应用于泛型编程,它允许在编译期间根据类型的特性来进行不同的操作或优化,而不需要在运行时进行额外的类型检查或转换。

typedef#define 的区别

1
2
3
// 语法对比
typedef existing_type new_type; // 创建类型别名
#define identifier value; // 创建宏定义

typedef#define 是 C++中用于创建类型别名和宏定义的两种不同的方式,它们有以下区别:

  • 作用域和类型安全性
    • typedef 创建的类型别名具有作用域,并且是类型安全的。它仅在特定的作用域内有效,并且可以进行类型检查;
    • #define 定义的宏没有作用域限制,是全局的替换文本。它是简单的文本替换,在预处理阶段将标识符替换为指定的文本,没有类型信息,也没有作用域;
  • 处理时机
    • typedef 在编译时进行处理,因此它保留了类型信息,并在编译期间执行类型检查;
    • #define 在预处理阶段进行处理,它仅仅是简单的文本替换,在编译器看到 #define 定义时就会立即替换,没有类型检查;

简而言之,#define 是宏定义,只是在预处理时进行简单的文本替换。而 typedef 是对类型定义别名,可以保存指定类型的类型信息。

Traits 技术在 STL 中的应用

在 STL 的实现中,容器和算法是分离的,这两者之间通过迭代器进行通信。算法使用迭代器来操作容器,且算法在使用迭代器操作容器的元素时往往还需要知道容器元素的类型。

1
2
3
4
5
6
7
// vector的简短定义
template <typename T>
class vector {
public:
typedef T value_type;
// ...
}

如何获取迭代器所指元素的类型呢,这时候就用到了 Traits 技术。Traits 技术实际上可以说是一种编程策略——利用模版技术来获取类型。在上面 vector 的简短定义中,我们在 public 中使用 typedefvector 的元素类型 T 保存在了 value_type 中,然后我们便可以通过一个类型萃取模版在编译期获得该 value_type

1
2
3
4
5
// 类型萃取
template <typename type>
struct type_traits {
typedef typename type::value_type value_type;
}

如下所示,可以使用 iterator_traits 获取一个迭代器的元素类型。

1
2
3
4
5
6
7
int main() {
std::vector<int> vec;
std::iterator_traits<std::vector<int>::iterator>::value_type val0 = 0;
std::vector<int>::iterator::value_type val1 = 1;
std::vector<int>::value_type val2 = 2;
std::cout << val0 << " " << val1 << " " << val2 << std::endl;
}