跟我学c++高级篇——静态反射实现之一


tree
tree 2023-11-30 10:14:38 51515
分类专栏: 资讯

一、非侵入式的静态反射(自省)

在前面分析过,反射有静态和动态两类形式,前者在编译期实现,后者在运行期实现。而针对c++这类天然不支持(或者说极弱支持)反射的语言,在实现上又可以分为侵入式和非侵入式实现。这个就更好理解了,侵入式需要在原代码上增加一些辅助代码,而非侵入式则不需要增加辅助代码。这个只要过一下脑子当然是后者好,但实际应用上到底哪种好,得看实际情况,不能一概而论。

二、利用宏实现静态反射

在前面的文章《C++中两个宏PRETTY_FUNCTION__和__FUNCSIG的应用》介绍过这两个宏(其实是一种宏),它可以对c++程序在编译期和运行期的问题所在有一个记录并反馈给开发者(也提到过使用这个宏可以实现一种编译期反射的方法)。但是不知道有没有读者注意到那篇文章的例程中运行结果的一些细节,它可以得到一些参数的类型。噢,这不就是反射想达到的一种目的么?那可不可以利用这个宏来实现一种反射的方式呢?答案是肯定的。先看一个简单的例子入手:

#include <iostream>
#ifdef _WIN64
#define __FUNC__ __FUNCSIG__
#else
#define __FUNC__  __PRETTY_FUNCTION__
#endif

template<typename T>
constexpr void Func()
{
    std::cout << __FUNC__ << std::endl;
}

void getType() {
    Func<int>();
}
int main()
{
    getType();
}

它的运行结果是:

//gcc
constexpr void Func() [with T = int]

这是不是很明显可以看到T的类型是int,那么最暴力最原始的方法就是直接对这个字符串进行解析,然后得到T和int,这样不就可以得类型了么。看一下下面的例子:

#include <iostream>
#include <string>

#ifdef _WIN64
#define __FUNC__ __FUNCSIG__
#else
#define __FUNC__  __PRETTY_FUNCTION__
#endif

std::string_view parseResult(std::string result) {
    //str = constexpr void Func() [with T = int]
    auto begin = result.find("T = ") + 4;
    auto end = result.find_last_of("]");
    return std::string_view{ result.data() + begin, end - begin };
}
template<typename T>
constexpr auto TypeInfo() {
    auto result =  __FUNC__;
    return parseResult(result);
}

class Example{
  int d = 0;
  void GetData(){std::cout<<"test"<<std::endl;}
};

int main()
{
    auto type = TypeInfo<Example>();
    std::cout<<type<<std::endl;
    type = TypeInfo<int>();
    std::cout<<type<<std::endl;
    type = TypeInfo<double>();
    std::cout<<type<<std::endl;

}

运行结果:

Example
int
double

当然针对不同的编译器和平台可能还会需要进行细节上的修改,但整体上的原则基本是相同的。

三、例程

下面再看一个针对枚举体的例程。枚举体是一种比较特殊的情况,它可以和整数隐式转换。C++11又推出了枚举类,看看下面的例子:

#include <iostream>
#include <string>

#ifdef _WIN64
#define __FUNC__ __FUNCSIG__
#else
#define __FUNC__  __PRETTY_FUNCTION__
#endif

enum class DataType{USB,PCI,HD};
enum DType{USB,PCI,HD};

template<auto T>
constexpr  auto TypeInfo()
{
    std::string type = __FUNC__;
    auto begin = type.find("T = ") + 4;
    auto end = type.find_last_of(']');
    return std::string_view{ type.data() + begin, end - begin };
}

int main()
{
    std::cout<<Func1<DataType::HD>()<<std::endl;
    std::cout<<Func1<DType::HD>()<<std::endl;
}

运行结果:

DataType::HD
HD

今天把使用宏PRETTY_FUNCTION来实现静态非侵入式的反射进行了一个初步的分析说明,然后下一步将继续分析枚举的反射,从此处打开一个缺口,让大家更好的明白反射的实现方式的一个切入点。

四、总结

反射写起来非常头痛,一个是不知道如何说起更有系统性;另外一个就是哪种反射更有利于实际的应用。所以反射这个系列可能会是一个很长期的总结过程,大家不要着急,一定会把坑慢慢填好。

网站声明:如果转载,请联系本站管理员。否则一切后果自行承担。

本文链接:https://www.xckfsq.com/news/show.html?id=29207
赞同 0
评论 0 条
treeL0
粉丝 0 发表 8 + 关注 私信
上周热门
如何使用 StarRocks 管理和优化数据湖中的数据?  2959
【软件正版化】软件正版化工作要点  2878
统信UOS试玩黑神话:悟空  2843
信刻光盘安全隔离与信息交换系统  2737
镜舟科技与中启乘数科技达成战略合作,共筑数据服务新生态  1270
grub引导程序无法找到指定设备和分区  1235
华为全联接大会2024丨软通动力分论坛精彩议程抢先看!  165
点击报名 | 京东2025校招进校行程预告  164
2024海洋能源产业融合发展论坛暨博览会同期活动-海洋能源与数字化智能化论坛成功举办  163
华为纯血鸿蒙正式版9月底见!但Mate 70的内情还得接着挖...  159
本周热议
我的信创开放社区兼职赚钱历程 40
今天你签到了吗? 27
信创开放社区邀请他人注册的具体步骤如下 15
如何玩转信创开放社区—从小白进阶到专家 15
方德桌面操作系统 14
我有15积分有什么用? 13
用抖音玩法闯信创开放社区——用平台宣传企业产品服务 13
如何让你先人一步获得悬赏问题信息?(创作者必看) 12
2024中国信创产业发展大会暨中国信息科技创新与应用博览会 9
中央国家机关政府采购中心:应当将CPU、操作系统符合安全可靠测评要求纳入采购需求 8

加入交流群

请使用微信扫一扫!