当前位置: 首页 > news >正文

跟我学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++总被称为难的原因。
因为其灵活,不容易掌握,而每个方法又有长处和不同的适应场景,这都需要开发者自己权衡,这就是难的原因。见仁见智,各取所需吧。

相关文章:

  • python动态圣诞下雪图
  • C-语言每日刷题
  • MySQL基础『数据类型』
  • echarts 地图
  • 微信扫码登录修改二维码的样式
  • git的安装及ssh配置(Linux)
  • Linux中top命令输出日志分析?
  • Kubernetes学习笔记-Part.01 Kubernets与docker
  • 如何使用群晖管家结合内网穿透实现公网远程访问本地黑群晖
  • Docker快速入门(docker加速,镜像,容器,数据卷常见命令操作整理)
  • 用C++语言编写的图书馆系统代码,包括图书录入、查询、插入、修改、删除和添加功能
  • RNN:文本生成
  • DAPP开发【02】Remix使用
  • Python----练习:使用面向对象实现报名系统开发
  • The template root requires exactly one element
  • 世微AP5125 DC-DC降压恒流 LED车灯电源驱动IC SOT23-6
  • 数字孪生压缩空气储能管控平台
  • AndroidStudio - 新版本 Logcat 使用详解
  • 网络和Linux网络_7(传输层)UDP和TCP协议(端口号+确认应答+超时重传+三次握手四次挥手)
  • C语言--每日选择题--Day28
  • 中保协发布《保险机构适老服务规范》,全面规范保险机构面向老年人提供服务的统一标准
  • 75万买299元路由器后续:重庆市纪委、财政局、教委联合调查
  • “11+2”复式票,宝山购彩者领走大乐透1170万头奖
  • 习近平致电祝贺阿尔巴尼斯当选连任澳大利亚总理
  • 水豚“豆包”出逃已40天,扬州茱萸湾景区追加悬赏
  • 《新时代的中国国家安全》白皮书(全文)