| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> C++知识库 -> C++编译期分支选择相关技术 -> 正文阅读 |
|
[C++知识库]C++编译期分支选择相关技术 |
程序员写的代码里,最核心的内容之一就是根据不同的条件判断执行不同的逻辑分支,也就是所谓的if else,而分支判断又可以分为运行时和编译期两种,运行时的判断大家都很熟悉,比如对于后端服务,根据请求里字段的不同走不同的逻辑分支。另一类则是编译期就可以确定的分支选择,通常和特定的类型有关,比如对于一个object pool,因为需要重复利用对象,我们可以写一个通用的函数模板来执行clear,不同的类型有不同的clear操作,同时编译期计算在性能上也有很大帮助,运行时就不需要再进行额外的判断或计算了,这也是模板元编程的核心理念。 一、函数重载和标签分发1.1 函数重载函数重载大家都不陌生,其实这也是C++里最基本的最常用的编译期分支选择技术,可以有多个同名的函数,编译器会根据实参和形参的匹配情况来选择最合适的版本。下面引用Exceptional C++ Style关于函数重载的一个例子:
以上的代码的函数重载主要有以下几个步骤: 通过函数重载,本质上也就是在编译期选择了不同的代码分支。 1.2 标签分发而标签分发(tag dispatch),则是对函数重载机制的利用,和我们平常习惯的函数重载不一样的点在于,会用一个参数仅仅作为一个标签,这个标签并不参与任何代码逻辑,仅仅用于指导编译器选择合适的重载版本,这也是标签分发名称的由来,标签分发通常是为了解决参数相同但需要走不同的函数的问题, 标签参数通常都是一个空类,此项技术在stl库里面也有大量使用(c++20之后可以用concept更方便地实现)。这里来看一个迭代器的例子,我们知道stl里不同容器的迭代器的类型是不一样的,对于list这种,因为底层是双链表,不能随机访问,只能每次向前向后挪一,属于bidirectional_iterator,而vector这种,因为底层是连续内存空间,因此可以直接进行指针运算跳到需要的位置,属于random_access_iterator。 我们再来看std::advance函数的实现,如果需要前进n,对于random_access_iterator,我们是可以直接+n的,而对于普通的forward_iterator_tag,只能n次单加,因此可以利用标签分发写出类似以下的实现: 下面是cppreference上的一个基于迭代器做自定义算法的标签分发的例子: 二、模板特化模板特化指的是除了主模板之外,针对特定的模板参数额外提供特定的实现,分为全特化合偏特化两种: 三、 SFINAESFINAE(Substitution Failure Is Not An Error),即替换失败不是错误,这是一条针对函数模板重载决议的规则,详细的定义是:当模板形参在替换成显式指定的类型或推导出的类型失败时,只是从重载集中丢弃这个特化,而不会直接导致编译失败。通俗地来说就是,在编译器check模板调用的过程中,尝试使用某些版本会导致failure并不会导致编译失败,只要有能够正常用的,其余的failure会被忽略,这也是模板元编程经常用到的一个重要特性。 SFINAE是个很古老的特性,c++11之前就被大量运用了,到了c++11之后,标准库提供了更多的组件来简化该特性的使用,c++ 20之后又引入了concept来更简单地实现SFINAE能做地事情,但鉴于现在20完全不普及,SFINAE仍然有比较重要的价值。 SFINAE规则在模板的各个涉及到参数的部分都能生效,主要可以分为以下三类: 3.1 类型相关这里列两个典型的例子: 3.2 表达式相关
3.3 偏特化相关
四、 if constexprconstexpr是C++11引入的一个关键字,表明是编译器常量,实际使用中有两种用途,一个是修饰变量,一个是修饰函数返回值,修饰变量表明该变量是编译期常量,必须编译器就能确定,否则会报错。而constexpr函数如果传入的实参是编译器已知的,就会产生编译器结果,否则和没有constexpr修饰的函数没有区别。const表示readonly,constexpr则进一步限定在编译器已知。 C++17进而引入了if constexpr语法,可以方便地进行编译期分支选择,比如以下方式可以定义一个通用的取值函数,输入既支持指针,也支持原始值: |
|
C++知识库 最新文章 |
【C++】友元、嵌套类、异常、RTTI、类型转换 |
通讯录的思路与实现(C语言) |
C++PrimerPlus 第七章 函数-C++的编程模块( |
Problem C: 算法9-9~9-12:平衡二叉树的基本 |
MSVC C++ UTF-8编程 |
C++进阶 多态原理 |
简单string类c++实现 |
我的年度总结 |
【C语言】以深厚地基筑伟岸高楼-基础篇(六 |
c语言常见错误合集 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 8:53:58- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |