求实现基于可变模板的无序类型组合唯一整数映射函数
实现无序类型组合的唯一整数标识函数
GetNumber 要实现一个不受类型顺序影响、为每种数据类型组合返回唯一整数的可变模板函数,核心思路分为两步:给单个类型分配唯一ID,对类型组合的ID进行无序化处理并生成唯一标识。以下是几种可行的实现方案:
方案一:基于类型ID排序的哈希计算
这种方案通过给每个类型分配唯一基础ID,将类型组合的ID排序后再计算哈希,确保顺序不同的同类型组合得到相同结果。
1. 单个类型的唯一ID生成
利用模板静态变量的特性,每个类型首次调用时会分配一个递增的唯一ID:
#include <array> #include <algorithm> template<typename T> size_t GetTypeID() { static size_t id = [](){ static size_t global_counter = 0; return global_counter++; }(); return id; }
2. 无序类型组合的哈希计算
收集所有类型的ID,排序后用哈希组合算法生成最终标识:
template<typename... Ts> size_t GetNumber() { std::array<size_t, sizeof...(Ts)> type_ids = {GetTypeID<Ts>()...}; std::sort(type_ids.begin(), type_ids.end()); size_t combined_hash = 0; // 使用经典的哈希组合算法降低冲突概率 for (size_t id : type_ids) { combined_hash ^= id + 0x9e3779b9 + (combined_hash << 6) + (combined_hash >> 2); } return combined_hash; }
方案二:基于std::type_index的实现
直接利用标准库的std::type_index获取类型的唯一标识,同样通过排序后哈希实现无序性:
#include <typeindex> #include <array> #include <algorithm> template<typename... Ts> size_t GetNumber() { std::array<std::type_index, sizeof...(Ts)> type_indices = {std::type_index(typeid(Ts))...}; std::sort(type_indices.begin(), type_indices.end()); size_t combined_hash = 0; for (const auto& ti : type_indices) { auto ti_hash = std::hash<std::type_index>()(ti); combined_hash ^= ti_hash + 0x9e3779b9 + (combined_hash << 6) + (combined_hash >> 2); } return combined_hash; }
方案三:绝对无冲突的整数映射
如果需要绝对唯一的整数(避免哈希冲突的极小概率),可以维护一个静态映射表,将排序后的类型ID组合映射到递增整数:
#include <array> #include <algorithm> #include <unordered_map> // 自定义std::array的哈希函数 struct ArrayHash { template<typename T, size_t N> size_t operator()(const std::array<T, N>& arr) const { size_t hash = 0; for (const T& val : arr) { hash ^= std::hash<T>()(val) + 0x9e3779b9 + (hash << 6) + (hash >> 2); } return hash; } }; template<typename T> size_t GetTypeID() { static size_t id = [](){ static size_t global_counter = 0; return global_counter++; }(); return id; } template<typename... Ts> size_t GetNumber() { using IDArray = std::array<size_t, sizeof...(Ts)>; static std::unordered_map<IDArray, size_t, ArrayHash> type_combo_map; static size_t global_counter = 0; IDArray type_ids = {GetTypeID<Ts>()...}; std::sort(type_ids.begin(), type_ids.end()); auto it = type_combo_map.find(type_ids); if (it != type_combo_map.end()) { return it->second; } // 分配新的唯一整数 return type_combo_map[type_ids] = global_counter++; }
使用说明
- 以上三种方案均满足
GetNumber<int, double>()与GetNumber<double, int>()返回相同值的要求 - 方案一、二存在极低的哈希冲突概率,适合大多数场景;方案三通过映射表保证绝对唯一,适合对唯一性要求极高的场景
- 可直接将
GetNumber的返回值作为unordered_map的键,或者数组的索引(若返回值范围可控),来存储和获取MyClass<DataTypes>的实例
内容的提问来源于stack exchange,提问作者fat
相关产品推荐
相关产品推荐

