如何在编译时生成所有键值类型组合的std::variant映射类型?
自动生成包含所有键值类型组合的std::variant
这个问题可以用C++模板元编程完美解决,不用手动硬编码所有键值组合。下面是一个可扩展的实现,能自动生成包含你指定的所有类型的键值对std::map的std::variant:
完整实现代码
#include <variant> #include <map> #include <tuple> #include <string> #include <type_traits> // 第一步:定义你需要支持的所有键/值类型 // 这里包含了基础类型和std::string,你可以按需添加更多类型(比如long long、char等) using SupportedTypes = std::tuple<int, bool, float, double, std::string>; // 辅助模板:为单个键类型生成所有值类型对应的std::map的variant template <typename K, typename ValueTuple> struct GenerateMapsForKey; template <typename K, typename... Vs> struct GenerateMapsForKey<K, std::tuple<Vs...>> { using Type = std::variant<std::map<K, Vs>...>; }; // 辅助模板:将多个variant的类型合并为一个统一的variant template <typename... Variants> struct MergeVariants; // 递归合并两个variant的类型 template <typename... Ts, typename... Us, typename... Rest> struct MergeVariants<std::variant<Ts...>, std::variant<Us...>, Rest...> { using Type = typename MergeVariants<std::variant<Ts..., Us...>, Rest...>::Type; }; // 递归终止条件:只剩一个variant,直接返回它的类型 template <typename... Ts> struct MergeVariants<std::variant<Ts...>> { using Type = std::variant<Ts...>; }; // 主模板:遍历所有键类型,生成对应的map variant并合并成最终类型 template <typename KeyTuple, typename ValueTuple> struct GenerateMapVariant; template <typename... Ks, typename ValueTuple> struct GenerateMapVariant<std::tuple<Ks...>, ValueTuple> { using Type = typename MergeVariants<typename GenerateMapsForKey<Ks, ValueTuple>::Type...>::Type; }; // 最终的MapCombinator类型,自动包含所有键值组合的std::map using MapCombinator = typename GenerateMapVariant<SupportedTypes, SupportedTypes>::Type; // 可选:验证生成的类型是否符合预期 static_assert(std::is_same_v< MapCombinator, std::variant< std::map<int, int>, std::map<int, bool>, std::map<int, float>, std::map<int, double>, std::map<int, std::string>, std::map<bool, int>, std::map<bool, bool>, std::map<bool, float>, std::map<bool, double>, std::map<bool, std::string>, std::map<float, int>, std::map<float, bool>, std::map<float, float>, std::map<float, double>, std::map<float, std::string>, std::map<double, int>, std::map<double, bool>, std::map<double, float>, std::map<double, double>, std::map<double, std::string>, std::map<std::string, int>, std::map<std::string, bool>, std::map<std::string, float>, std::map<std::string, double>, std::map<std::string, std::string> > >);
代码说明
SupportedTypes:这是核心的类型列表,你只需要在这里添加或移除需要支持的键/值类型,比如要添加
long long,直接改成std::tuple<int, bool, float, double, std::string, long long>即可。GenerateMapsForKey:针对单个键类型
K,遍历ValueTuple里的所有值类型,生成包含std::map<K, V>(V为所有值类型)的variant。MergeVariants:递归地将多个variant的类型合并成一个大的variant,这样就能把每个键对应的map variant整合到一起。
GenerateMapVariant:遍历
KeyTuple里的所有键类型,为每个键生成对应的map variant,再通过MergeVariants合并成最终的MapCombinator类型。
使用方式
你可以像之前手动定义的MapCombinator一样直接使用这个自动生成的类型,比如:
#include <iostream> int main() { MapCombinator myMap = std::map<std::string, int>{{"age", 25}}; std::visit([](const auto& map) { using MapType = decltype(map); std::cout << "Map type: std::map<" << typeid(typename MapType::key_type).name() << ", " << typeid(typename MapType::mapped_type).name() << ">\n"; }, myMap); return 0; }
这样就能完全替代手动硬编码的variant,而且扩展性极强,新增类型只需要修改SupportedTypes即可。
内容的提问来源于stack exchange,提问作者Infinity
相关产品推荐
相关产品推荐

