C++反射之检测struct或class是否实现指定函数

news2025/1/12 6:51:14

目录

1.引言

2.检测结构体或类的静态函数

3.检测结构体或类的成员函数

3.1.方法1

3.2.方法2


1.引言

        诸如Java, C#这些语言是设计的时候就有反射支持的。c++没有原生的反射支持。并且,c++提供给我们的运行时类型信息非常少,只是通过typeinfo提供了有限的一些支持。这一点点支持其实连类型名都无法打印好。更别说去检测一个结构体或类是否具有实现指定函数。

        通过编写模板代码和std::enable_ifrequires(C++20)表达式,你可以根据某个类型是否拥有特定的成员函数或方法来启用或禁用某些代码。这种方法不会直接告诉你一个类型是否实现了某个函数,但它允许你根据类型的能力编写条件编译的代码。如:

template<typename T, typename = void>  
struct has_func_impl : std::false_type {};  
  
template<typename T>  
struct has_func_impl<T, std::void_t<decltype(std::declval<T&>().func())>> : std::true_type {};  
  
template<typename T>  
constexpr bool has_func_v = has_func_impl<T>::value;  
  
// 使用示例  
struct MyClass {  
    void func() {}  
};  
  
static_assert(has_func_v<MyClass>); // 成功

2.检测结构体或类的静态函数

C++之std::declval-CSDN博客

1)通过编写一个模板结构和它的特化版本来检测是否存在某个成员函数。

2)使用std::declval来在编译时模拟对成员函数的调用。

3)如果调用成功,则特化版本继承自std::true_type,否则继承自std::false_type

代码如下:

#define HAS_MEMBER_EX(member)\
template<typename T, typename... Args> struct has_member_ex_##member{\
private:\
    template<typename U> \
	static auto Check(int) -> decltype(U::member(std::declval<Args>()...), std::true_type()); \
	template<typename U> \
	static std::false_type Check(...); \
public:\
	enum { value = std::is_same<decltype(Check<T>(0)), std::true_type>::value }; \
}; \

HAS_MEMBER_EX(getDataSize)

测试代码:

//A1具有静态getDataSize()函数
class A1{
public:
    static int getDataSize() {
        return 100;
    }
};

//A2只有成员函数getDataSize()函数
class A2{
public:
    int getDataSize() {
        return 100;
    }
};

//A3无函数
class A3{
   
};

int main()
{
    constexpr bool bA1 = has_member_ex_getDataSize<A1>::value; //输出: true
    constexpr bool bA2 = has_member_ex_getDataSize<A2>::value; //输出: false
    constexpr bool bA3 = has_member_ex_getDataSize<A3>::value; //输出: false

    return 0;
}

3.检测结构体或类的成员函数

3.1.方法1

也是利用std::declval结合decltype来判断是否具有某个函数,代码如下:

#define HAS_NON_STATIC_MEMBER_EX(member)\
template<typename T, typename... Args> struct has_non_static_member_ex_##member{\
private:\
    template<typename U> \
	static auto Check(int) -> decltype(std::declval<U>()().member(std::declval<Args>()...), std::true_type()); \
	template<typename U> \
	static std::false_type Check(...); \
public:\
	enum { value = std::is_same<decltype(Check<T>(0)), std::true_type>::value }; \
}; \

HAS_NON_STATIC_MEMBER_EX(getDataSize)

  测试代码:

//A1,A2,A3同上,省略

int main()
{
    constexpr bool bA1 = has_non_static_member_ex_getDataSize<A1>::value; //输出: true
    constexpr bool bA2 = has_non_static_member_ex_getDataSize<A2>::value; //输出: true
    constexpr bool bA3 = has_non_static_member_ex_getDataSize<A3>::value; //输出: false

    return 0;
}

        我们使用std::declval<U>()::member()来尝试“调用”该类型的member成员函数(而不需要创建一个实际的对象)。如果这行代码在编译时有效(即U类型有一个无参数且返回类型为可推导的member成员函数),那么我们就特化Check()std::true_type;否则,我们保持其默认实现为std::false_type

3.2.方法2

实现代码如下:

#define HAS_NON_STATIC_MEMBER_EX1(R, member) \
template<typename T> struct has_non_static_member_ex1_##member{ \
private:\
	template<typename Y, Y y>	\
	class Helper;	\
	template<typename U = T>	\
	constexpr static bool has##member(...) {\
		return false;\
	}\
	template<typename U = T>\
	constexpr static bool has##member(Helper<R (U::*)()const, &U::member>*) {\
		return true;\
	}\
public:\
	static const bool value = has##member<T>(nullptr);\
};\

HAS_NON_STATIC_MEMBER_EX1(int, getDataSize)

测试代码同上。

推荐阅读

C++之std::declval

C++模板函数重载规则细说

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1654435.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Julia 语言环境安装与使用

1、Julia 语言环境安装 安装教程&#xff1a;https://www.runoob.com/julia/julia-environment.html Julia 安装包下载地址为&#xff1a;https://julialang.org/downloads/。 安装步骤&#xff1a;注意&#xff08;勾选 Add Julia To PATH 自动将 Julia 添加到环境变量&…

【Linux 性能详解】CPU性能分析工具篇

目录 uptime mpstat 实时监控 查看特定CPU核心 pidstart 监控指定进程 组合多个监控类型 监控线程资源 按用户过滤进程 vmstart 用途 基本用法 输出字段 perf execsnoop dstat 通俗解释 技术层面解释 使用示例 总结 uptime uptime 是一个在 Linux 和 Unix…

暴打前任互动玩法开播教程

暴打前任互动玩法开播教程 暴打前任互动玩法开播教程【相关直播互动插件咩播需要额外官方购买】 网盘自动获取 链接&#xff1a;https://pan.baidu.com/s/1lpzKPim76qettahxvxtjaQ?pwd0b8x 提取码&#xff1a;0b8x

小微公司可用的开源ERP系统

项目介绍 华夏ERP是基于SpringBoot框架和SaaS模式的企业资源规划&#xff08;ERP&#xff09;软件&#xff0c;旨在为中小企业提供开源且易用的ERP解决方案。它专注于提供进销存、财务和生产功能&#xff0c;涵盖了零售管理、采购管理、销售管理、仓库管理、财务管理、报表查询…

Redis集群.md

Redis集群 本章是基于 CentOS7 下的 Redis 集群教程&#xff0c;包括&#xff1a; 单机安装RedisRedis主从Redis分片集群 1.单机安装Redis 首先需要安装Redis所需要的依赖&#xff1a; yum install -y gcc tcl然后将课前资料提供的Redis安装包上传到虚拟机的任意目录&#xf…

将ESP工作为AP路由模式并当成服务器

将ESP8266模块通过usb转串口接入电脑 ATCWMODE3 //1.配置成双模ATCIPMUX1 //2.使能多链接ATCIPSERVER1 //3.建立TCPServerATCIPSEND0,4 //4.发送4个字节在链接0通道上 >ATCIPCLOSE0 //5.断开连接通过wifi找到安信可的wifi信号并连接 连接后查看自己的ip地址变为192.168.4.…

【系统架构师】-选择题(十二)

1、网闸的作用&#xff1a;实现内网与互联网通信&#xff0c;但内网与互联网不是直连的 2、管理距离是指一种路由协议的路由可信度。15表示该路由信息比较可靠 管理距离越小&#xff0c;它的优先级就越高&#xff0c;也就是可信度越高。 0是最可信赖的&#xff0c;而255则意味…

【管理咨询宝藏95】SRM采购平台建设内部培训方案

本报告首发于公号“管理咨询宝藏”&#xff0c;如需阅读完整版报告内容&#xff0c;请查阅公号“管理咨询宝藏”。 【管理咨询宝藏95】SRM采购平台建设内部培训方案 【格式】PDF版本 【关键词】SRM采购、制造型企业转型、数字化转型 【核心观点】 - 重点是建设一个适应战略采…

ue引擎游戏开发笔记(35)——为射击添加轨道,并显示落点

1.需求分析&#xff1a; 我们只添加了开枪特效&#xff0c;事实上并没有实际的效果产生例如弹痕&#xff0c;落点等等。所以逐步实现射击的完整化&#xff0c;先从实现落点开始。 2.操作实现&#xff1a; 1.思路&#xff1a;可以这样理解&#xff0c;每次射击的过程是一次由摄…

MM模块学习一(供应商创建,物料类型的定义及功能)

物料管理流程&#xff1a; 源头&#xff1a;采购需求->采购申请 MRP&#xff1a;物料需求计划。运行物料需求计划的结果&#xff0c;根据物料的性质来判断是外购&#xff08;采购申请&#xff09;或者是生产&#xff08;计划订单->生产订单&#xff09;。 采购申请&am…

Bugku Crypto 部分题目简单题解

抄错的字符 题目描述&#xff1a; 老师让小明抄写一段话&#xff0c;结果粗心的小明把部分数字抄成了字母&#xff0c;还因为强迫症把所有字母都换成大写。你能帮小明恢复并解开答案吗&#xff1a; QWIHBLGZZXJSXZNVBZW 观察疑似base64解码&#xff0c;尝试使用cyberchef解码…

多模态EDA论文小记

论文地址 该论文主要改进点是&#xff1a;通过动态化局部搜索中每个集群大小&#xff0c;高斯和柯西分布共同产生个体。总的来说改进点不多&#xff0c;当然也可能是笔者还没发现。 局部搜索 划分集群 划分集群有两个策略分别是&#xff1a; 随机生成一个点作为中心点&…

Spring Boot | Spring Boot 整合 “RabbitMQ“ ( 消息中间件 ) 实现

目录: Spring Boot 整合 "RabbitMQ" ( 消息中间件 )实现 &#xff1a;一、Spring Boot 整合 整合实现 : Publish/Subscribe ( 发布订阅 ) 工作模式 ( "3种"整合实现方式 )1.1 基于"API"的方式 ( 实现 Publish/Subscribe "发布订阅"工作…

【智能楼宇秘籍】一网关多协议无缝对接BACnet+OPC+MQTT

在繁华的都市中心&#xff0c;一座崭新的大型商业综合体拔地而起&#xff0c;集购物、餐饮、娱乐、办公于一体&#xff0c;是现代城市生活的缩影。然而&#xff0c;这座综合体的幕后英雄——一套高度集成的楼宇自动化系统&#xff0c;正是依靠多功能协议网关&#xff0c;实现了…

VALSE 2024 Workshop报告分享┆ 大规模自动驾驶仿真系统研究

视觉与学习青年学者研讨会&#xff08;VALSE&#xff09;旨在为从事计算机视觉、图像处理、模式识别与机器学习研究的中国青年学者提供一个广泛而深入的学术交流平台。该平台旨在促进国内青年学者的思想交流和学术合作&#xff0c;以期在相关领域做出显著的学术贡献&#xff0c…

精通GDBus:Linux IPC的现代C接口

目录标题 1. GDBus介绍2. GDBus的优点3. 安装GDBus4. 使用GDBus连接到D-Bus总线实现D-Bus服务调用D-Bus方法发送和接收信号 5. 总结 在Linux环境下&#xff0c;不同的程序需要通过某种方式进行通信和协同工作。GDBus是GLib库的一部分&#xff0c;提供了一个基于GObject系统的、…

英语新概念2-回译法-lesson13

The Greenwood Boys 绿林少年是一组流行歌手们。现在他们正在参观城市里的所有公园&#xff0c;他们明天就要到这。他们将坐火车到并且大多数小镇上的年轻人将要欢迎他们&#xff0c;明天晚上他们将要在工人俱乐部唱歌。绿林少年将在这待五天&#xff0c;在这期间&#xff0c;…

Redis集群分片

什么是集群 集群是由多个复制集组成的,能提供在多个redis节点间共享数据的程序集 简而言之就是将原来的单master主机拆分为多个master主机,将整个数据集分配到各主机上 集群的作用 集群中可以存在多个master,而每个master可以挂载多个slave自带哨兵的故障转移机制,不需要再去…

华为车BU迈入新阶段,新任CEO对智能车的3个预判

作者 |张马也 编辑 |德新 4月24日&#xff0c;北京车展前夕&#xff0c;华为召开了新一年的智能汽车解决方案新品发布会。 这次发布会&#xff0c;也是华为智能汽车解决方案BU&#xff08;简称「车BU」&#xff09;CEO 靳玉志的公开首秀。 一开场&#xff0c;靳玉志即抛出了…

刷题训练之模拟

> 作者&#xff1a;დ旧言~ > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;熟练掌握模拟算法。 > 毒鸡汤&#xff1a;学习&#xff0c;学习&#xff0c;再学习 ! 学&#xff0c;然后知不足。 > 专栏选自&#xff1a;刷题训…