如何根据DataType枚举值获取对应C++类型以简化文件读取代码?
解决枚举到C++类型映射并简化模板函数调用的方案
你需要将运行时读取的DataType枚举值映射到对应C++基础类型,以此避免在switch中重复编写readData<T>的调用代码,以下是几种可行的实现方案:
方案一:类型映射模板 + 编译期分发
通过模板特化建立枚举与类型的一一映射,再封装分发函数简化switch逻辑:
1. 定义类型映射模板
#include <cstdint> enum DataType { kInt8, kUint16, kInt16, kUint32, kInt32, kUint64, kInt64, kFloat16, kFloat32, kFloat64 }; // 模板特化实现枚举到类型的映射 template<DataType D> struct TypeMap; template<> struct TypeMap<kInt8> { using type = int8_t; }; template<> struct TypeMap<kUint16> { using type = uint16_t; }; template<> struct TypeMap<kInt16> { using type = int16_t; }; template<> struct TypeMap<kUint32> { using type = uint32_t; }; template<> struct TypeMap<kInt32> { using type = int32_t; }; template<> struct TypeMap<kUint64> { using type = uint64_t; }; template<> struct TypeMap<kInt64> { using type = int64_t; }; template<> struct TypeMap<kFloat16> { using type = float16_t; }; // 需确保编译器支持float16_t template<> struct TypeMap<kFloat32> { using type = float; }; template<> struct TypeMap<kFloat64> { using type = double; };
2. 封装分发函数
// 假设你的模板函数readData定义如下 template<typename T> void readData(T* data, size_t numElements) { // 读取逻辑实现 } // 编译期绑定类型的分发函数 template<DataType D> void dispatchReadData(void* data, size_t numElements) { using T = typename TypeMap<D>::type; readData<T>(static_cast<T*>(data), numElements); } // 运行时switch调用分发函数 void readByDataType(DataType type, void* data, size_t numElements) { switch(type) { case kInt8: dispatchReadData<kInt8>(data, numElements); break; case kUint16: dispatchReadData<kUint16>(data, numElements); break; case kInt16: dispatchReadData<kInt16>(data, numElements); break; case kUint32: dispatchReadData<kUint32>(data, numElements); break; case kInt32: dispatchReadData<kInt32>(data, numElements); break; case kUint64: dispatchReadData<kUint64>(data, numElements); break; case kInt64: dispatchReadData<kInt64>(data, numElements); break; case kFloat16: dispatchReadData<kFloat16>(data, numElements); break; case kFloat32: dispatchReadData<kFloat32>(data, numElements); break; case kFloat64: dispatchReadData<kFloat64>(data, numElements); break; } }
此方案将类型转换和模板调用逻辑集中到dispatchReadData,switch中仅需一行调用代码,大幅减少冗余。
方案二:std::variant + std::visit(C++17及以上)
利用std::variant存储所有可能的指针类型,通过std::visit统一处理模板函数调用:
1. 定义variant类型与访问器
#include <variant> #include <cstdint> enum DataType { /* 枚举定义同前 */ }; template<typename T> void readData(T* data, size_t numElements) { /* 读取逻辑 */ } // 包含所有目标类型指针的variant using DataPtrVariant = std::variant< int8_t*, uint16_t*, int16_t*, uint32_t*, int32_t*, uint64_t*, int64_t*, float16_t*, float*, double* >; // 访问器:统一处理readData调用 struct ReadDataVisitor { size_t numElements; template<typename T> void operator()(T* ptr) const { readData<T>(ptr, numElements); } };
2. 运行时转换并调用
void readByDataType(DataType type, void* data, size_t numElements) { DataPtrVariant var; // 仅在switch中做指针类型转换 switch(type) { case kInt8: var = static_cast<int8_t*>(data); break; case kUint16: var = static_cast<uint16_t*>(data); break; case kInt16: var = static_cast<int16_t*>(data); break; case kUint32: var = static_cast<uint32_t*>(data); break; case kInt32: var = static_cast<int32_t*>(data); break; case kUint64: var = static_cast<uint64_t*>(data); break; case kInt64: var = static_cast<int64_t*>(data); break; case kFloat16: var = static_cast<float16_t*>(data); break; case kFloat32: var = static_cast<float*>(data); break; case kFloat64: var = static_cast<double*>(data); break; } // 统一调用readData std::visit(ReadDataVisitor{numElements}, var); }
此方案将模板调用逻辑封装到访问器中,switch仅负责类型转换,代码更简洁。
方案三:编译期枚举遍历(C++20及以上)
利用C++20的constexpr特性和整数序列,自动生成分发逻辑,避免手写switch:
#include <array> #include <cstdint> enum DataType { /* 枚举定义同前 */ }; template<typename T> void readData(T* data, size_t numElements) { /* 读取逻辑 */ } // 类型映射模板同方案一 template<DataType D> struct TypeMap; // ... 所有特化定义同前 // 编译期枚举序列 constexpr std::array all_data_types = { kInt8, kUint16, kInt16, kUint32, kInt32, kUint64, kInt64, kFloat16, kFloat32, kFloat64 }; // 编译期分发逻辑 template<DataType D> constexpr void handle_type(DataType type, void* data, size_t numElements) { if (type == D) { using T = typename TypeMap<D>::type; readData<T>(static_cast<T*>(data), numElements); } } // 遍历所有枚举值处理 void readByDataType(DataType type, void* data, size_t numElements) { [&]<size_t... Is>(std::index_sequence<Is...>) { (handle_type<all_data_types[Is]>(type, data, numElements), ...); }(std::make_index_sequence<all_data_types.size()>{}); }
此方案无需手写switch,通过编译期遍历自动匹配枚举值并调用对应模板函数,适合枚举值较多的场景。
内容的提问来源于stack exchange,提问作者user18490
相关产品推荐
相关产品推荐

