news 2026/4/17 21:04:07

C++编程实践—false_type和true_type的实践应用

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++编程实践—false_type和true_type的实践应用

一、说明

c++标准中提供了元编程接口std::integral_constant,而在这个接口中又提供了针对bool类型的两个实例化类型:

true_type std::integral_constant<bool,true>false_type std::integral_constant<bool,false>

在前面的文章分析中,特别是针对std::index_sequence的相关文章中,对其进行过介绍。另外在分析其它模板和元编程的过程中,也对它们进行过顺便的应用说明。但对它们的应用并没有系统性的说明。本文将针对其实际应用的方式进行整体的总结说明。

二、应用形式

在模板或元编程中,true_type和false_type基本有两种应用形式:

  1. 用作基类
    这种是最典型的情况,比如前面的成员检测:
template<typename T,typename=void>structcheckSize:std::false_type{};template<typename T>structcheckSize<T,std::void_t<decltype(std::declval<T>().size())>>:std::true_type{};

而在元编程库中的很多接口都继承自它们,比如std::is_pointer等:

template<class T>structis_pointer:std::false_type{};template<class T>structis_pointer<T*>:std::true_type{};template<class T>structis_pointer<T*const>:std::true_type{};template<class T>structis_pointer<T*volatile>:std::true_type{};template<class T>structis_pointer<T*constvolatile>:std::true_type{};

在实际的开发中,这种情况也是非常常见的。

  1. 标签分发处理
    这种情况主要有函数重载处理、静态断言和条件编译:
#include<iostream>#include<type_traits>#include<utility>structCopyType{};structMoveType{MoveType()=default;MoveType(constMoveType&)=delete;MoveType(MoveType&&)=default;};template<typename T>voidtestFunc(T value,std::true_type){std::cout<<"call copy!"<<std::endl;}template<typename T>voidtestFunc(T value,std::false_type){std::cout<<"call move!"<<std::endl;}template<typename T>voidprocess(T value){testFunc(std::forward<T>(value),std::is_copy_constructible<T>{});}intmain(){CopyType ct;process(ct);MoveType nct;process(std::move(nct));return0;}

其它的实现也都类似,不再过多列举。

三、实现方法

std::false_type和std::true_type是从std::integral_constant扩展而来的,所以需要看integral_constant具体的实现:

template<class T,T v>structintegral_constant{staticconstexpr T value=v;using value_type=T;using type=integral_constant;// using injected-class-nameconstexpr operatorvalue_type()constnoexcept{returnvalue;}constexpr value_typeoperator()()constnoexcept{returnvalue;}// since c++14};template<bool B>using bool_constant=integral_constant<bool,B>;using true_type=integral_constant<bool,true>;using false_type=integral_constant<bool,false>;

大家可以尝试着用不同的方式来实现并进行工程验证。

四、例程

下面给出一个例程供大家分析:

#include<iostream>#include<type_traits>// 正确转换函数template<typename F,typename T>voidcastType(constF&from,T&to,std::true_type){to=static_cast<T>(from);std::cout<<"cast ok!"<<std::endl;}//错误处理函数template<typename F,typename T>voidcastType(constF&from,T&to,std::false_type){static_assert(std::is_convertible<F,T>::value,"convertible result");std::cout<<"cast error"<<std::endl;}template<typename F,typename T>voidcastCheckRun(constF&from,T&to){castType(from,to,std::is_convertible<F,T>{});}intmain(){intd=1;doubledd=0.0;std::string str="abc";castCheckRun(d,dd);//castCheckRun(d, str); //errorreturn0;}

再看一下std::is_function的源码实现:

template<class>structis_function:std::false_type{};// specialization for regular functionstemplate<class Ret,class...Args>structis_function<Ret(Args...)>:std::true_type{};// specialization for variadic functions such as std::printftemplate<class Ret,class...Args>structis_function<Ret(Args......)>:std::true_type{};// specialization for function types that have cv-qualifierstemplate<class Ret,class...Args>structis_function<Ret(Args...)const>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args...)volatile>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args...)constvolatile>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args......)const>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args......)volatile>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args......)constvolatile>:std::true_type{};// specialization for function types that have ref-qualifierstemplate<class Ret,class...Args>structis_function<Ret(Args...)&>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args...)const&>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args...)volatile&>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args...)constvolatile&>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args......)&>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args......)const&>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args......)volatile&>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args......)constvolatile&>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args...)&&>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args...)const&&>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args...)volatile&&>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args...)constvolatile&&>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args......)&&>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args......)const&&>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args......)volatile&&>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args......)constvolatile&&>:std::true_type{};// specializations for noexcept versions of all the above (C++17 and later)template<class Ret,class...Args>structis_function<Ret(Args...)noexcept>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args......)noexcept>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args...)constnoexcept>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args...)volatilenoexcept>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args...)constvolatilenoexcept>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args......)constnoexcept>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args......)volatilenoexcept>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args......)constvolatilenoexcept>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args...)&noexcept>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args...)const&noexcept>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args...)volatile&noexcept>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args...)constvolatile&noexcept>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args......)&noexcept>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args......)const&noexcept>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args......)volatile&noexcept>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args......)constvolatile&noexcept>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args...)&&noexcept>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args...)const&&noexcept>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args...)volatile&&noexcept>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args...)constvolatile&&noexcept>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args......)&&noexcept>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args......)const&&noexcept>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args......)volatile&&noexcept>:std::true_type{};template<class Ret,class...Args>structis_function<Ret(Args......)constvolatile&&noexcept>:std::true_type{};

std::is_function处理的原理基本是函数类型(对象)不能有cv限定符且不能绑定到非const的左值引用(可绑定到const的左传引用或右值引用)。当然实际应用时一般是使用函数在地址转换时会隐式的转为函数指针。不过看上面的代码可以发现,其实为了编译处理更简单,就是靠量大管饱,大量特化相关的函数判断即可。
也可以这样理解,通过模板偏特化(partial specialization)列出可能的全部函数类型签名形式,对合法的函数类型进行std::true_type特化;其它由非函数类型则由匹配主模板,特化为 std::false_type。

五、总结

元编程和模板编程的复杂是大家公认的,但只要大家从基础的知识点出发,将不同的基础知识灵活运用起来,再加上多看网上开源的好的工程代码,就能够较快的掌握元编程和模板编程的技术。与诸君共勉!

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

支持AQLM压缩算法!逼近FP16精度的极高压缩率

支持AQLM压缩算法&#xff01;逼近FP16精度的极高压缩率 在大模型参数规模不断突破千亿甚至万亿的今天&#xff0c;部署成本和推理效率已成为横亘在科研与落地之间的巨大鸿沟。一个70B级别的语言模型动辄需要数张A100才能运行&#xff0c;这让大多数企业和开发者望而却步。更严…

作者头像 李华
网站建设 2026/4/17 1:20:54

Vanta.js:打造惊艳3D动态背景的终极指南 [特殊字符]

Vanta.js&#xff1a;打造惊艳3D动态背景的终极指南 &#x1f680; 【免费下载链接】vanta Animated 3D backgrounds for your website 项目地址: https://gitcode.com/gh_mirrors/va/vanta 想要为你的网站添加令人惊叹的3D动态背景效果吗&#xff1f;Vanta.js正是你需要…

作者头像 李华
网站建设 2026/4/18 3:28:18

数据质量管理的艺术:大数据环境下的5大最佳实践

数据质量管理的艺术&#xff1a;大数据环境下的5大最佳实践——从混乱到可信的进阶之路 摘要/引言 想象一下&#xff1a;某电商平台花费数百万预算推出“618大促”精准营销活动&#xff0c;却因为用户行为数据中“重复点击”字段的统计错误&#xff0c;导致推荐算法把高端奢侈品…

作者头像 李华
网站建设 2026/4/17 20:26:01

Kubo项目实战指南:新手避坑与高效使用技巧

Kubo作为IPFS的第一个Go语言实现&#xff0c;是分布式文件系统的核心工具。本文将分享Kubo项目的快速上手指南和避坑技巧&#xff0c;帮助新手轻松掌握节点部署和文件管理。 【免费下载链接】kubo An IPFS implementation in Go 项目地址: https://gitcode.com/gh_mirrors/ku…

作者头像 李华
网站建设 2026/4/18 7:54:42

Boring Notch:让MacBook刘海变身智能交互中心的5个创意玩法

Boring Notch&#xff1a;让MacBook刘海变身智能交互中心的5个创意玩法 【免费下载链接】boring.notch TheBoringNotch: Not so boring notch That Rocks &#x1f3b8;&#x1f3b6; 项目地址: https://gitcode.com/gh_mirrors/bor/boring.notch 你是否曾对着MacBook屏…

作者头像 李华
网站建设 2026/4/18 3:24:28

深度解析IEEE802.3-2022标准:网络工程师的权威技术指南

深度解析IEEE802.3-2022标准&#xff1a;网络工程师的权威技术指南 【免费下载链接】IEEE802.3-2022标准全文下载分享 - **文件名称**: IEEE802.3-2022标准全文.pdf- **文件大小**: 100MB- **文件格式**: PDF- **文件内容**: IEEE802.3-2022标准的完整内容&#xff0c;包括所有…

作者头像 李华