代码实现
#include <iostream>
#include <vector>
// 自定义编译期常量,代表数据类型大小
#define DATA_TYPE_SIZE 8
// 根据DATA_TYPE_SIZE选择不同的内部数据存储结构
#if!defined(DATA_TYPE_SIZE) || DATA_TYPE_SIZE <= 4
using storage_type = std::vector<char>;
#else
using storage_type = std::vector<int>;
#endif
template <typename T>
class CustomTemplate {
private:
storage_type data;
public:
CustomTemplate() = default;
void addElement(T element) {
// 根据storage_type的实际类型添加元素
if constexpr (std::is_same_v<storage_type, std::vector<char>>) {
data.resize(data.size() + sizeof(T));
char* ptr = data.data() + data.size() - sizeof(T);
new (ptr) T(element);
} else if constexpr (std::is_same_v<storage_type, std::vector<int>>) {
data.push_back(*reinterpret_cast<int*>(&element));
}
}
void printData() {
if constexpr (std::is_same_v<storage_type, std::vector<char>>) {
for (size_t i = 0; i < data.size(); i += sizeof(T)) {
T value;
std::memcpy(&value, data.data() + i, sizeof(T));
std::cout << value << " ";
}
} else if constexpr (std::is_same_v<storage_type, std::vector<int>>) {
for (int val : data) {
std::cout << val << " ";
}
}
std::cout << std::endl;
}
};
代码工作原理
- 宏定义判断:通过
#if!defined(DATA_TYPE_SIZE) || DATA_TYPE_SIZE <= 4
判断自定义编译期常量DATA_TYPE_SIZE
是否定义以及其值是否小于等于4。如果满足条件,则storage_type
定义为std::vector<char>
;否则定义为std::vector<int>
。
- 模板类定义:
CustomTemplate
模板类内部使用storage_type
作为数据存储结构。addElement
成员函数根据storage_type
的实际类型来添加元素,printData
成员函数根据storage_type
的实际类型来打印数据。
#if!defined宏定义的优势
- 简单直观:宏定义的语法简单,对于根据简单编译期常量进行条件选择的场景,代码逻辑一目了然。
- 与编译环境紧密结合:可以直接利用编译器的预处理功能,在编译早期就完成条件判断,不依赖于运行时的任何逻辑。
#if!defined宏定义的劣势
- 缺乏类型安全性:宏定义是简单的文本替换,没有类型检查。例如,如果在宏定义中写错了类型名称,编译器在预处理阶段不会报错,可能导致难以调试的错误。
- 灵活性受限:宏定义只能基于编译期常量进行判断,对于一些复杂的编译期计算或基于模板参数的条件选择,宏定义无法满足需求。而模板元编程的
std::conditional
等工具可以基于模板参数进行更灵活的条件选择。