主页 > IT业界  > 

跟我学c++高级篇——动态反射之二动态列表

跟我学c++高级篇——动态反射之二动态列表
一、动态生成列表

在上一篇中实现了一个Map映射,其实就是一个表。但那个表有点维护和扩展上的不方便,所以后为又开始用静态展开递归的方式来遍历枚举。其不管是怎么做,都是要得到整个枚举体的信息,然后才能进行处理。 这次使用一个动态生成表的方式来进行查询,得到相关的枚举的具体的信息。

二、例程

先看一个例程,然后分析一下:

#include <string> #include <array> #include <utility> #include <type_traits> #include <iostream> #ifdef _WIN64 #define __FUNC__ __FUNCSIG__ #else #define __FUNC__ __PRETTY_FUNCTION__ #endif enum class DataType {USB,PCI,HD,NOT}; template<auto T> constexpr auto TypeInfo() { std::string_view type = __FUNC__; auto begin = type.find("T = ") + 4; auto end = type.find_last_of(']'); return std::string_view{ type.data() + begin, end - begin }; } constexpr auto n = static_cast<int>(DataType::NOT); template<typename T> constexpr auto enumMapName (T t) { //constexpr auto n = TypeCount<T>(); constexpr std::array<std::string_view,n> mapNames { [] <std::size_t... Is>(std::index_sequence<Is...>) { return std::array<std::string_view,n>{ TypeInfo<static_cast<T>(Is)>()... }; }(std::make_index_sequence<n>{}) }; return mapNames[static_cast<std::size_t>(t)]; } int main() { DataType dt = DataType::USB; std::cout << enumMapName(dt) << std::endl; for(auto i = 0; i < n; ++i) { std::cout << enumMapName(static_cast<DataType>(i)) << std::endl; } //调用方式 //std::cout<<TypeInfo<DataType::HD>()<<std::endl; //std::cout<<TypeInfo<DataType(6)>()<<std::endl; //std::cout<<TypeInfo<DataType(1)>()<<std::endl; }

如果是在c++20上可以增加一个“概念”控制(类似SFINAE),“requires std::is_enum_v”,做一下安全性的验证,其实在这里只是限定在枚举里进行反射的讨论,它可以不考虑。 上面的代码中,求枚举的数量有点暴力简单,其实也可以用其它一些方法来实现,比如下面的两种方式都可以:

//first #include <iostream> #define DefineEnum(Name, Type, ...) \ enum class Name { \ __VA_ARGS__ \ ,count=std::size({__VA_ARGS__}) }; #define Enum(Name, ...) DefineEnum(Name, int, __VA_ARGS__) Enum(DataType,USB,PCI,HD); //second-需要借助前面的函数 template<typename T, std::size_t N = 0> constexpr auto TypeCount() { constexpr auto v = static_cast<T>(N); if constexpr (TypeInfo<v>().find("(") == std::string_view::npos){ return TypeCount<T, N + 1>(); } else{ return N; } }

第一种方法需要用宏来定义产生枚举,第二种使用了类似于前面静态反射中的判断特定字符,这里使用小括号,也可以否定的使用“::”,TypeInfo返回值类似下面:

auto TypeInfo() [with auto T = DataType::HD] DataType::HD auto TypeInfo() [with auto T = (DataType)6] (DataType)6 auto TypeInfo() [with auto T = DataType::PCI]

如果给一个不在范围内的枚举变量则会产生上面的效果(如前面代码注释部分)。方法有很多,看哪种更适合实际的应用即可。

三、总结

在上文说过,本来这篇是和上一篇打算合在一起,可是又觉得它们有点不同的意思,就拆分了开来。其实说来归去,重点是理解如何进行反射前的准备,把相关的字段名称都准备出来,只是同一个基础的应用,却可以在上层写出不同的反射方法来,这也是c++总被称为难的原因。 因为其灵活,不容易掌握,而每个方法又有长处和不同的适应场景,这都需要开发者自己权衡,这就是难的原因。见仁见智,各取所需吧。

标签:

跟我学c++高级篇——动态反射之二动态列表由讯客互联IT业界栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“跟我学c++高级篇——动态反射之二动态列表