You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求实现基于可变模板的无序类型组合唯一整数映射函数

实现无序类型组合的唯一整数标识函数 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 11:35:34