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

C++模板参数包忽略顺序生成类型组合唯一ID实现方案问询

C++ 编译期无顺序依赖类型组合ID实现方案

核心解决思路

通过编译期对类型参数包按固定规则排序,消除输入顺序的影响,排序后的类型组合只要元素相同,最终生成的类型标识完全一致,天然兼容类型别名(别名与原类型属于同一类型,排序规则下会被识别为同一元素)。

完整实现代码

基础运行时版本(C++17及以上兼容)

#include <type_traits>
#include <typeindex>
#include <string_view>

// 编译期获取类型唯一标识字符串(适配多编译器)
template <typename T>
constexpr std::string_view type_name() {
    #ifdef _MSC_VER
    return __FUNCSIG__;
    #else
    return __PRETTY_FUNCTION__;
    #endif
}

// 类型比较规则:按类型标识字符串的字典序排序
template <typename A, typename B>
constexpr bool type_less = type_name<A>() < type_name<B>();

// 类型列表容器
template <typename... Ts>
struct type_list {};

// 编译期插入单个类型到已排序的类型列表
template <typename T, typename SortedList>
struct insert_type;

template <typename T, typename... SortedTs>
struct insert_type<T, type_list<SortedTs...>> {
    template <typename... Accum>
    struct impl;

    // 找到比当前类型大的元素,插入到该元素前
    template <typename... Accum, typename Next, typename... Rest>
    requires (type_less<T, Next>)
    struct impl<type_list<Accum...>, Next, Rest...> {
        using type = type_list<Accum..., T, Next, Rest...>;
    };

    // 当前元素更小,继续向后遍历
    template <typename... Accum, typename Next, typename... Rest>
    struct impl<type_list<Accum...>, Next, Rest...> {
        using type = typename impl<type_list<Accum..., Next>, Rest...>::type;
    };

    // 所有元素都更小,插入到列表末尾
    template <typename... Accum>
    struct impl<type_list<Accum...>> {
        using type = type_list<Accum..., T>;
    };

    using type = typename impl<type_list<>, SortedTs...>::type;
};

// 编译期对类型列表排序
template <typename List>
struct sort_type_list;

template <>
struct sort_type_list<type_list<>> {
    using type = type_list<>;
};

template <typename T, typename... Ts>
struct sort_type_list<type_list<T, Ts...>> {
    using sorted_rest = typename sort_type_list<type_list<Ts...>>::type;
    using type = typename insert_type<T, sorted_rest>::type;
};

// 目标函数实现
template <typename... Ts>
auto foo() {
    // 对输入类型参数包排序,相同类型组合排序结果完全一致
    using sorted_types = typename sort_type_list<type_list<Ts...>>::type;
    return std::type_index(typeid(sorted_types));
}

验证效果

  • foo<int, char, bool>() == foo<char, int, bool>() 结果为true
  • foo<int>() == foo<char>() 结果为false
  • 存在类型别名时:using my_type = char; foo<bool, int, my_type>() == foo<bool, char, int>() 结果为true

零运行时开销优化版本(C++20及以上)

如果需要编译期常量ID,可以直接对排序后的类型标识字符串做哈希,完全消除运行时开销:

// 编译期FNV-1a哈希算法
constexpr size_t fnv1a_hash(std::string_view s) {
    size_t hash = 14695981039346656037ULL;
    for (char c : s) {
        hash ^= static_cast<size_t>(c);
        hash *= 1099511628211ULL;
    }
    return hash;
}

template <typename... Ts>
constexpr size_t foo() {
    using sorted_types = typename sort_type_list<type_list<Ts...>>::type;
    return fnv1a_hash(type_name<sorted_types>());
}

该版本返回值为编译期常量,运行时无任何计算开销。

内容的提问来源于stack exchange,提问作者Lauren S

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 22:09:03