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

跟我学C++中级篇—std::conjunction手动实现

一、说明

在前面学习和分析了元编程的逻辑操作。如果在C++17以前没有提供这几个逻辑模板操作应该怎么做呢?虽然已经有了轮子,但是不是可以逆向一下这个轮子,自己尝试着再造一个类似的轮子,会不会能够更好的理解其内在的实现原理和机制呢?

二、定义和实现

在这里仅以std::conjunction为例来进行逻辑模板的实现,先看一下在cppreference上的实现:

template<class...>structconjunction:std::true_type{};template<class B1>structconjunction<B1>:B1{};template<class B1,class...Bn>structconjunction<B1,Bn...>:std::conditional_t<bool(B1::value),conjunction<Bn...>,B1>{};

再看一下库中的实现:

template<typename...>struct__and_;template<>struct__and_<>:public true_type{};template<typename _B1>struct__and_<_B1>:public _B1{};template<typename _B1,typename _B2>struct__and_<_B1,_B2>:public __conditional_t<_B1::value,_B2,_B1>{};template<typename _B1,typename _B2,typename _B3,typename..._Bn>struct__and_<_B1,_B2,_B3,_Bn...>:public __conditional_t<_B1::value,__and_<_B2,_B3,_Bn...>,_B1>{};template<typename..._Bn>structconjunction:__and_<_Bn...>{};

两者的实现基本类似,都是先实现特化版本用来终止变参模板的条件(不明白可以看一下前面变参模板相关的文章),然后conditional_t来递归的处理逻辑类型值的结果。

三、实现源码及分析

下面看看用别的方法是否也可以实现类似的代码逻辑操作。看下面的代码:

#include<iostream>#include<type_traits>// 普通模板,空参数返回true_typetemplate<typename...>struct__and__:std::true_type{};// 递归特化并检查条件template<typename T,typename...Rest>struct__and__<T,Rest...>:std::integral_constant<bool,T::value&&__and__<Rest...>::value>{};// 模拟AND实现template<typename...Cond>using __and_t__=__and__<Cond...>;// 多and检测template<typename T,typename=void>structcheck_mul_attr:std::false_type{};template<typename T>structcheck_mul_attr<T,std::void_t<decltype(std::declval<T>().test()),decltype(std::declval<T>().display()),typename T::nestType>>:__and_t__<std::is_same<decltype(std::declval<T>().test()),void>,std::is_same<decltype(std::declval<T>().display()),int>,std::is_convertible<typename T::nestType,int>>{};// 测试结构体structAllAttr{//static void test(){}voidtest(){}intdisplay(){return0;}using nestType=int;};structPartialAttr{voidtest(){}using nestType=int;};structNothing{};intmain(){// 测试AND逻辑std::cout<<"all have: "<<check_mul_attr<AllAttr>::value<<std::endl;// 1std::cout<<"partial: "<<check_mul_attr<PartialAttr>::value<<std::endl;// 0std::cout<<"nothing: "<<check_mul_attr<Nothing>::value<<std::endl;// 0// 测试__and_t__std::cout<<"test and result True: "<<__and_t__<std::true_type,std::true_type>::value<<std::endl;// 1std::cout<<"test and result False: "<<__and_t__<std::true_type,std::false_type>::value<<std::endl;// 0return0;}

编译展开后的代码为:

#include<iostream>#include<type_traits>template<typename...type_parameter_0_0>struct__and__:public std::integral_constant<bool,true>{};/* First instantiated from: insights.cpp:8 */#ifdefINSIGHTS_USE_TEMPLATEtemplate<>struct__and__<std::is_same<int,int>,std::is_convertible<int,int>>:public std::integral_constant<bool,true>{};#endif/* First instantiated from: insights.cpp:8 */#ifdefINSIGHTS_USE_TEMPLATEtemplate<>struct__and__<std::is_convertible<int,int>>:public std::integral_constant<bool,true>{};#endif/* First instantiated from: insights.cpp:8 */#ifdefINSIGHTS_USE_TEMPLATEtemplate<>struct__and__<>:public std::integral_constant<bool,true>{};#endif/* First instantiated from: insights.cpp:8 */#ifdefINSIGHTS_USE_TEMPLATEtemplate<>struct__and__<std::integral_constant<bool,true>>:public std::integral_constant<bool,true>{};#endif/* First instantiated from: insights.cpp:8 */#ifdefINSIGHTS_USE_TEMPLATEtemplate<>struct__and__<std::integral_constant<bool,false>>:public std::integral_constant<bool,false>{};#endif/* First instantiated from: insights.cpp:18 */#ifdefINSIGHTS_USE_TEMPLATEtemplate<>struct__and__<std::is_same<void,void>,std::is_same<int,int>,std::is_convertible<int,int>>:public std::integral_constant<bool,true>{};#endif/* First instantiated from: insights.cpp:43 */#ifdefINSIGHTS_USE_TEMPLATEtemplate<>struct__and__<std::integral_constant<bool,true>,std::integral_constant<bool,true>>:public std::integral_constant<bool,true>{};#endif/* First instantiated from: insights.cpp:44 */#ifdefINSIGHTS_USE_TEMPLATEtemplate<>struct__and__<std::integral_constant<bool,true>,std::integral_constant<bool,false>>:public std::integral_constant<bool,false>{};#endiftemplate<typename T,typename...Rest>struct__and__<T,Rest...>:public std::integral_constant<bool,T::value&&__and__<Rest...>::value>{};template<typename...Cond>using __and_t__=__and__<Cond...>;template<typename T,typename type_parameter_0_1=void>structcheck_mul_attr:public std::integral_constant<bool,false>{};/* First instantiated from: insights.cpp:38 */#ifdefINSIGHTS_USE_TEMPLATEtemplate<>structcheck_mul_attr<AllAttr,void>:public __and__<std::is_same<void,void>,std::is_same<int,int>,std::is_convertible<int,int>>{};#endif/* First instantiated from: insights.cpp:39 */#ifdefINSIGHTS_USE_TEMPLATEtemplate<>structcheck_mul_attr<PartialAttr,void>:public std::integral_constant<bool,false>{};#endif/* First instantiated from: insights.cpp:40 */#ifdefINSIGHTS_USE_TEMPLATEtemplate<>structcheck_mul_attr<Nothing,void>:public std::integral_constant<bool,false>{};#endiftemplate<typename T>structcheck_mul_attr<T,std::void_t<decltype(std::declval<T>().test()),decltype(std::declval<T>().display()),typename T::nestType>>:public __and_t__<std::is_same<decltype(std::declval<T>().test()),void>,std::is_same<decltype(std::declval<T>().display()),int>,std::is_convertible<typename T::nestType,int>>{};structAllAttr{inlinevoidtest(){}inlineintdisplay(){return0;}using nestType=int;};structPartialAttr{inlinevoidtest(){}using nestType=int;};structNothing{};intmain(){std::operator<<(std::cout,"all have: ").operator<<(std::integral_constant<bool,true>::value).operator<<(std::endl);std::operator<<(std::cout,"partial: ").operator<<(std::integral_constant<bool,false>::value).operator<<(std::endl);std::operator<<(std::cout,"nothing: ").operator<<(std::integral_constant<bool,false>::value).operator<<(std::endl);std::operator<<(std::cout,"test and result True: ").operator<<(std::integral_constant<bool,true>::value).operator<<(std::endl);std::operator<<(std::cout,"test and result False: ").operator<<(std::integral_constant<bool,false>::value).operator<<(std::endl);return0;}

这段代码中需要说明的std::void_t对于非正常类型是无法转换出void的,所以正常情况下就检查到了包含内部的函数或属性等。另外,还需要注意decltype(std::declval().test())这段代码,如果在T的属性中,test函数声明为静态的,则可以直接使用decltype(T::test()),否则就只能按现在的情况先使用declval在编译期生成一个对象然后再调用test函数的类型检测。
check_mul_attr多and检测默认是false_type,然后偏特化另外一个检测版本,当上面代码说明中的void成功转换后则选中这个特化版本,即可进行连续的and控制。

四、总结

重复造轮子好不好没有一个标准的答案,但如果造轮子是出于学习的目的,如果这个轮子规模不太大的情况下,一定是个好事。学习最忌的是“知其然不知其所以然”,因为这种情况下,往往无法灵活主动的有机结合各种技术解决问题。大多数情况下往往是高级的“生搬硬套”,这就会带来各种各样的问题。关键是这些问题不一定会在当下暴露出来,然而当其真正暴露出来时,就可能是一个大问题。

http://www.jsqmd.com/news/240333/

相关文章:

  • CJA | 北航罗明强教授团队:一种基于生成式人工智能的快速结构化飞行器概念设计方法
  • 企业源代码防泄密软件,该怎么选?
  • 计算机毕业设计springboot校园闲置交易平台 基于SpringBoot的校园二手交易系统设计与实现 SpringBoot框架下的校园闲置物品交易管理平台开发
  • Vue 3的中文文献
  • 基于Django的连锁火锅智慧餐饮管理系统 计算机毕业设计选题 计算机毕设项目 前后端分离【源码-文档报告-代码讲解】
  • C++ 中仿函数和函数对象这两个术语的区别
  • 从资产到智能:数据如何重塑企业估值与增长模型
  • 计算机毕业设计springboot“木成林”学生互助平台的设计与实现 基于Spring Boot的“学林互助”学生服务平台设计与实现 Spring Boot框架下“林聚学”学生互助系统的设计与开发
  • 让资产“活”起来!复杂美“万物上链•WEB3商城”亮相2025全球数字贸易博览会
  • 《Light》突破性成果:2μm波段InP基量子点激光器性能超越传统量子阱结构
  • 创客匠人:智能体赋能老年康养 IP—— 从单兵服务到人机协同的适老化变现革命
  • 我们不是卖产品,而是在交付一种人生的意义
  • 互联网大厂Java面试实战:Spring Boot、微服务与AI技术全解析
  • 学习 Python,用哪个编辑器比较好
  • 创客匠人:智能体重构露营户外 IP—— 从风口赚快钱到长期变现的效率革命
  • 创客匠人:智能体赋能儿童美育 IP—— 从单兵教学到人机协同的创意变现革命
  • 创客匠人:智能体重构社区团购运营 IP—— 从单兵管理到人机协同的效率变现革命
  • 科技赋能洁净厂区 明诺E810FB助力江苏上骐集团绿色发展
  • 从点击到对话:AI 时代的未来购物,人机交互方式的全面变革
  • 国产算力首证具身大脑模型训练实力:摩尔线程联合智源研究院完成RoboBrain 2.5全流程训练
  • 如何在WordPress网站中添加Cookie弹窗
  • 《Amazon账号注册与养号:从“能登录”到“不被风控”》
  • 2026年最佳双屏游戏KVM:为何TESmart HDK202-M24专为高刷设备而生
  • PHP接口请求超时完整排查与解决方案(从代码到服务器)
  • 深度学习:python老照片修复系统 卷积神经网络CNN算法 图片修复 深度学习 Django框架 pytorch 大数据毕业设计(建议收藏)
  • 【cursor】前后端分离项目下的AI跨工程管理方案
  • 产线级MES系统如何实现生产进度的实时监控?
  • 机器学习:python电影票房数据可视化分析系统 不同档期电影票房Flask框架 艺恩电影票房网站 requests爬虫(建议收藏)
  • 数据治理和数据管理,到底有啥区别?一张图讲清楚
  • 创客匠人:智能体构建 IP 数字组织 —— 从单兵作战到人机协同的知识变现革命