如何构建可追加类型的constexpr TypeVector并实现存储类型反向查询
问题根因
你当前的实现思路本质是做了编译期类型擦除:将类型映射为唯一const char*值的同时,丢失了值和类型的静态关联,C++模板系统无法自动完成值到类型的反向推导,因此才需要手动编写特化,也无法支持模板实例的批量适配。
最优解决方案
采用无类型擦除的编译期类型列表实现,所有类型信息直接保存在TypeVector的模板参数中,完全避免反向映射的问题,无需任何手动特化:
#include <type_traits> #include <tuple> #include <utility> // 类型标签工具,C++20可直接用std::type_identity,低版本可自行实现 template <typename T> struct type_identity { using type = T; }; template <typename... Ts> struct TypeVector { // 当前容器存储的类型数量 static constexpr size_t size = sizeof...(Ts); // 获取指定下标对应的类型标签 template <size_t I> constexpr auto get() const noexcept { return type_identity<std::tuple_element_t<I, std::tuple<Ts...>>>{}; } // 追加类型,返回新的TypeVector实例 template <typename T> constexpr auto push_back() const noexcept { return TypeVector<Ts..., T>{}; } // 删除指定下标类型,返回新的TypeVector实例 template <size_t I> constexpr auto erase() const noexcept { return []<size_t... Is>(std::index_sequence<Is...>) { auto pick_type = []<size_t J>(std::integral_constant<size_t, J>) { if constexpr (J < I) return type_identity<std::tuple_element_t<J, std::tuple<Ts...>>>{}; else return type_identity<std::tuple_element_t<J+1, std::tuple<Ts...>>>{}; }; return TypeVector<typename decltype(pick_type(std::integral_constant<size_t, Is>{}))::type...>{}; }(std::make_index_sequence<sizeof...(Ts)-1>{}); } }; // 反向获取类型工具,无需任何手动特化 template <typename T> struct retrieve_type; template <typename T> struct retrieve_type<type_identity<T>> { using type = T; }; template <typename T> using retrieve_type_t = typename retrieve_type<T>::type;
使用示例
和你给出的预期伪代码完全对齐,天然支持任意模板实例化类型:
// 测试用模板类,无需做任何额外适配 template <typename T> struct SomeTemplateClass {}; consteval auto build_vector() { TypeVector<> x; auto x1 = x.push_back<int>(); auto x2 = x1.push_back<float>(); // 直接追加模板实例化类型即可 auto x3 = x2.push_back<SomeTemplateClass<double>>(); return x3; } static constexpr auto my_vector = build_vector(); // 直接获取对应位置类型 retrieve_type_t<decltype(my_vector.get<0>())> some_variable = 0; // 等价于int some_variable = 0; retrieve_type_t<decltype(my_vector.get<1>())> some_variable2 = 0.0f; // 等价于float some_variable2 = 0.0f; retrieve_type_t<decltype(my_vector.get<2>())> some_variable3{}; // 等价于SomeTemplateClass<double> some_variable3{};
方案优势
- 零手动特化成本:自动支持所有C++类型,包括任意深度的模板实例化类型
- 纯编译期操作:无任何运行时开销
- 兼容性好:仅依赖C20标准特性,无需第三方库。如果需要兼容C17,仅需将
consteval改为constexpr,调整部分参数包展开语法即可。 - 可扩展性强:可以很方便的追加插入、排序、遍历等编译期类型操作,也可以直接替换为Boost.Mp11等成熟元编程库的
mp_list容器,内置了所有常用的类型列表操作能力。
内容的提问来源于stack exchange,提问作者SomeProgrammer
相关产品推荐
相关产品推荐

