news 2026/6/10 19:03:02

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
跟我学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控制。

四、总结

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 13:30:33

做好项目管理的4条潜规则,比埋头干活更管用

项目管理的核心是搞定事、管好人&#xff0c;但只盯着甘特图、里程碑的“硬操作”远远不够。那些藏在流程背后的职场潜规则&#xff0c;往往决定着项目的成败。看懂并顺应这些规则&#xff0c;能让你的项目推进事半功倍。沟通到位&#xff0c;比方案完美更重要 很多项目经理会陷…

作者头像 李华
网站建设 2026/6/10 13:27:55

大模型实战(三):快速搭建基于RAG知识库的智能聊天助手,在本地部署的开源大模型应用平台Dify Xinference

我们分享了关于如何在本地私有化部署开源大模型应用平台Dify&#xff0c;并成功将Xinference内的3个模型&#xff08;语言模型、嵌入模型以及重排序模型&#xff09;集成到Dify中。那么在本篇文章&#xff0c;我们将基于所集成的模型能力来尝试搭建一个基于RAG知识库的智能聊天…

作者头像 李华
网站建设 2026/6/10 11:49:34

2026年最佳双屏游戏KVM:为何TESmart HDK202-M24专为高刷设备而生

高刷新率显示器、HDR画质以及性能强劲的显卡&#xff0c;早已成为核心游戏玩家和创作者的标配。但很多用户在搭建设备时&#xff0c;总会忽略一个关键部件——KVM切换器。 在双电脑、双显示器的使用场景中&#xff0c;一款劣质KVM可能会悄悄拖垮你的设备性能&#xff1a;导致刷…

作者头像 李华
网站建设 2026/6/10 13:31:12

4358535

5352655

作者头像 李华
网站建设 2026/6/10 11:08:17

Manus数据手套为机器人灵巧手训练、遥操作提供精确手指数据

人工智能机器人培训MANUS数据手套的可扩展学习使用MANUS手套训练机器人灵巧的手&#xff1a;专为超精确手指跟踪和实时动作捕捉而设计。手套可以捕捉高分辨率的运动数据无缝集成到机器学习管道中-支持开发类似人类的抓取和操纵行为。轻松的人工智能模型集成机器人学习的精确演示…

作者头像 李华