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

如何统一管理C++类集合并自动生成静态constexpr值到类的反向映射?

问题:基于序列化常量的类反向映射与批量操作自动化

场景说明

我有一组接口近似的可扩展类,每个类都包含一个用于序列化的唯一静态constexpr常量,示例如下:

class A {
    constexpr static int value = 0;
};

class B {
    constexpr static int value = 1;
};

当前实现的痛点

我目前通过手动编写模板特化实现从value到类的反向映射:

template <int value> struct type_for_value { };
template <> struct type_for_value<0> { using type = A; };
template <> struct type_for_value<1> { using type = B; };

但每次新增类(如类C)时,必须手动添加对应的模板特化。同时,遍历整个类集合的函数也需要同步修改参数包:

constexpr auto for_each_class(auto const& func) {
    return func.template operator()<A, B>();
}

需求

是否存在一种方案(优先使用参数包这类强类型实现,也可接受宏),只需一次性定义类集合,就能在编译时自动生成反向映射的模板特化,同时让批量遍历函数直接复用该集合?

我曾尝试用带参数包的结构体实现,但无法正确生成模板特化,且for_each_class的别名也无法正常工作:

template <typename... T>
struct all_classes_impl {
    constexpr static auto for_each_class(auto const& func) {
        return func.template operator()<T...>();
    }

    template <int value>
    struct type_for_value { };

    template <>
    struct type_for_value<T::value> {
        using type = T;
    }...;
};

using all_classes = all_classes_impl<A, B>;
constexpr auto for_each_class = &all_classes::for_each_class;

可行解决方案

核心思路

利用参数包继承展开自动生成反向映射的模板特化,结合C++17折叠表达式实现批量遍历,只需维护一个类集合即可完成所有关联逻辑。

完整实现代码

#include <type_traits>
#include <iostream>

// 原始类定义(调整为public访问或添加友元确保value可被访问)
class A {
    constexpr static int value = 0;
public:
    static constexpr int get_value() { return value; }
    friend struct type_map_entry_helper<A>;
};

class B {
    constexpr static int value = 1;
public:
    static constexpr int get_value() { return value; }
    friend struct type_map_entry_helper<B>;
};

// 基础模板:默认无对应类型
template <int value>
struct type_map_entry { };

// 辅助模板:为单个类生成对应的type_map_entry特化
template <typename T>
struct type_map_entry_helper : type_map_entry<T::value> {
    using type = T;
};

// 类集合结构体:整合反向映射与批量操作
template <typename... Ts>
struct class_collection : type_map_entry_helper<Ts>... {
    // 批量遍历:对每个类调用func的operator()<T>
    constexpr static void for_each(auto&& func) {
        (func.template operator()<Ts>(), ...);
    }

    // 反向映射:从value获取对应类类型
    template <int value>
    using type_for_value = typename type_map_entry<value>::type;
};

// 定义全局类集合
using all_classes = class_collection<A, B>;

使用示例

1. 反向映射验证

// 获取value=0对应的类
using TypeA = all_classes::type_for_value<0>;
static_assert(std::is_same_v<TypeA, A>, "TypeA should be A");

// 获取value=1对应的类
using TypeB = all_classes::type_for_value<1>;
static_assert(std::is_same_v<TypeB, B>, "TypeB should be B");

2. 批量遍历操作

// 定义处理单个类的函数对象
struct PrintClassValue {
    template <typename T>
    constexpr void operator()() const {
        std::cout << "Class value: " << T::get_value() << std::endl;
    }
};

// 遍历所有类并输出value
int main() {
    all_classes::for_each(PrintClassValue{});
    return 0;
}
// 输出:
// Class value: 0
// Class value: 1

新增类的便捷性

当新增类C时,只需修改all_classes的定义即可,无需修改其他逻辑:

class C {
    constexpr static int value = 2;
public:
    static constexpr int get_value() { return value; }
    friend struct type_map_entry_helper<C>;
};

// 更新类集合
using all_classes = class_collection<A, B, C>;

此时type_for_value<2>会自动映射到C,for_each也会自动遍历C。

关键细节说明

  • 访问权限:如果类的value是private的,需要将type_map_entry_helper<T>声明为友元,或者提供public的getter方法。
  • 继承展开原理:class_collection继承了type_map_entry_helper<Ts>...,每个type_map_entry_helper<T>会特化type_map_entry<T::value>并添加type成员,从而自动完成所有反向映射的特化。
  • 折叠表达式:(func.template operator()<Ts>(), ...)是C++17的折叠表达式,用于遍历参数包中的每个类型并执行函数调用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 13:05:27