如何在编译时从类型集合中获取对应整数值?
编译时类型-整数值映射的C17/C20实现
C++17 解决方案
C++17里可以通过模板变量特化实现编译时的类型到整数的映射,这种方式简单直接,代码量少:
#include <string> #include <type_traits> // 基础模板,默认值为0 template<typename T> constexpr int TypeMap = 0; // 为需要映射的类型逐一特化,指定对应整数值 template<> constexpr int TypeMap<int> = 1; template<> constexpr int TypeMap<char> = 2; template<> constexpr int TypeMap<double> = 4; template<> constexpr int TypeMap<std::string> = 8; template<> constexpr int TypeMap<const char*> = 8; // 适配字符串字面量类型 struct MyStructure { // 补充默认构造函数,满足main里直接创建对象的需求 MyStructure() = default; MyStructure(char* d, int size) {} template<typename T> MyStructure& operator=(const T& arg) { // 用std::decay_t处理参数的const/引用等修饰,确保类型匹配 type_ = TypeMap<std::decay_t<T>>; return *this; } int type_ = 0; }; int main() { MyStructure myStruct; myStruct = 1; // type_被设为1 myStruct = 'a'; // type_被设为2 myStruct = 3.14; // type_被设为4 myStruct = std::string("test"); // type_被设为8 myStruct = "Hello world"; // type_被设为8 }
思路说明
- 定义通用模板变量
TypeMap,默认值为0; - 为每个需要映射的类型编写特化版本,指定对应的整数值;
- 赋值运算符模板中,用
std::decay_t去除参数类型的const、引用等修饰,确保能匹配到对应的特化模板,直接获取编译时确定的整数值赋值给type_。
C++20 解决方案
C++20带来了模板lambda、std::type_identity等新特性,可以把类型映射表集中管理,扩展性更好:
#include <string> #include <type_traits> #include <tuple> struct MyStructure { MyStructure() = default; MyStructure(char* d, int size) {} // 编译时类型-值映射表,用tuple集中存储所有映射关系 static constexpr auto type_map = std::make_tuple( std::pair(std::type_identity<int>{}, 1), std::pair(std::type_identity<char>{}, 2), std::pair(std::type_identity<double>{}, 4), std::pair(std::type_identity<std::string>{}, 8), std::pair(std::type_identity<const char*>{}, 8) ); // 编译时查找函数,用模板lambda+折叠表达式遍历tuple template<typename T> static constexpr int find_type_value() { using TargetT = std::decay_t<T>; return [&]<std::size_t... I>(std::index_sequence<I...>) { // 遍历所有tuple元素,匹配类型后返回对应值 return (... + (std::is_same_v<TargetT, typename std::tuple_element_t<I, decltype(type_map)>::first::type> ? std::get<I>(type_map).second : 0)); }(std::make_index_sequence<std::tuple_size_v<decltype(type_map)>>{}); } template<typename T> MyStructure& operator=(const T& arg) { type_ = find_type_value<T>(); return *this; } int type_ = 0; }; int main() { MyStructure myStruct; myStruct = 1; // type_被设为1 myStruct = 'a'; // type_被设为2 myStruct = 3.14; // type_被设为4 myStruct = std::string("test"); // type_被设为8 myStruct = "Hello world"; // type_被设为8 }
思路说明
- 用
std::type_identity包装类型,把所有类型-值的映射关系集中放在type_map这个constexpr tuple里; - 利用C++20的模板lambda和索引序列,在编译时遍历tuple,通过
std::is_same_v匹配目标类型,找到对应的整数值; - 新增映射关系时,只需要在
type_map里添加一对std::pair即可,无需额外编写模板特化,维护更方便。
内容的提问来源于stack exchange,提问作者Wad
相关产品推荐
相关产品推荐

