constexpr与std::is_same_v碰撞会产生什么火花?

2024-03-30 05:20

本文主要是介绍constexpr与std::is_same_v碰撞会产生什么火花?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. 只编译会用到的if分支

示例代码一中,checkType_v1checkType_v2两个函数的区别就是if的条件里一个加了constexpr一个没加,加与不加从结果来看都一样,那在编译时和运行时各有什么区别呢?

示例代码一test_01.cpp

// g++  test_01.cpp  -std=c++17#include <iostream>
#include <type_traits>template<class T>
void checkType_v1(T){if constexpr (std::is_same_v<T, int>){std::cout << "Input is an int.\n";}else if constexpr (std::is_same_v<T, float>){std::cout << "Input is a float.\n";}else if constexpr (std::is_same_v<T, double>){std::cout << "Input is a double.\n";}else{std::cout << "Unsupported type!\n";}
}template<class T>
void checkType_v2(T){if (std::is_same_v<T, int>){std::cout << "Input is an int.\n";}else if (std::is_same_v<T, float>){std::cout << "Input is a float.\n";}else if (std::is_same_v<T, double>){std::cout << "Input is a double.\n";}else{std::cout << "Unsupported type!\n";}
}int main(){checkType_v1(4);   // Input is an int.checkType_v1(4.f); // Input is a float.checkType_v1(4.0); // Input is a double.checkType_v1('A'); // Unsupported type!checkType_v2(4);   // Input is an int.checkType_v2(4.f); // Input is a float.checkType_v2(4.0); // Input is a double.checkType_v2('A'); // Unsupported type!    
}

【来自C++大咖吴老师的解答】如果你要调用一个只接受某种类型的函数,那就必须用 if constexpr。此外,用 if constexpr 条件判断是编译是做出的,没用到的分支完全不会在某个类型的特化里产生二进制代码。

举例说明,也就是说针对checkType_v1的版本,假设调用它的时候传入的是int类型的参数,那么编译的二进制文件中只有代码里的第一个分支的实现。而checkType_v2的版本的二进制文件中是有整个函数的实现。

这么做的目的有如下三个(其中第三个最重要):

  1. 降低运行时的判断时间;
  2. 减少编译后二进制文件的大小;
  3. 【来自C++大咖吴老师的解答】但最重要的是,有些情况下你对特定类型要走的分支在其他类型的情况下可能完全编译不通过!比如,vector可以reservedeque不可以;deque可以push_frontvector不可以。

2. 验证上面第3点

示例代码二test_02.cpp

// g++  test_02.cpp  -std=c++17
#include <iostream>
#include <type_traits>
#include <typeinfo>
#include <vector>
#include <set>
#include <deque>template<class Container>
void expandContainer(Container& container, int val){if constexpr (std::is_same_v<Container, std::vector<int>>){container.push_back(val);for(const auto&it: container){std::cout << it << ", ";}std::cout << "vector number added.\n";}else if constexpr (std::is_same_v<Container, std::deque<int>>){container.push_front(val);for(const auto&it: container){std::cout << it << ", ";}std::cout << "deque number added.\n";}else{container.insert(val);for(const auto&it: container){std::cout << it << ", ";}std::cout << "Other container number added.\n";}
}int main(){std::vector<int> vec{1,2,3};expandContainer(vec,100);     // 1, 2, 3, 100, vector number added.std::deque<int> deq{4,5,6};expandContainer(deq, 200);    // 200, 4, 5, 6, deque number added.std::set<int> aset{7,8,9};expandContainer(aset, 300);   // 7, 8, 9, 300, Other container number added.

假如去掉constexpr,如示例代码三test_03.cpp

#include <iostream>
#include <type_traits>
#include <typeinfo>
#include <vector>
#include <set>
#include <deque>template<class Container>
void expandContainer(Container& container, int val){if constexpr (std::is_same_v<Container, std::vector<int>>){container.push_back(val);for(const auto&it: container){std::cout << it << ", ";}std::cout << "vector number added.\n";}else if /*constexpr*/ (std::is_same_v<Container, std::deque<int>>){container.push_front(val);for(const auto&it: container){std::cout << it << ", ";}std::cout << "deque number added.\n";}else{container.insert(val);for(const auto&it: container){std::cout << it << ", ";}std::cout << "Other container number added.\n";}
}int main(){std::vector<int> vec{1,2,3};expandContainer(vec,100);     // 1, 2, 3, 100, vector number added.//std::deque<int> deq{4,5,6};//expandContainer(deq, 200);    // 200, 4, 5, 6, deque number added.std::set<int> aset{7,8,9};expandContainer(aset, 300);   // 7, 8, 9, 300, Other container number added.
}

此时编译会有如下报错:
在这里插入图片描述
走哪个分支如果在编译时无法确定那么就要保障运行时所有的分支都可以走,很显然else if的分支中有push_front操作,但std::set不支持,所以编译会报错。
因此,如果传入的参数只能走特定的分支,只能在编译时就限制住走的路径,即使用if constexprelse if constexpr

这篇关于constexpr与std::is_same_v碰撞会产生什么火花?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/860587

相关文章

c++中std::placeholders的使用方法

《c++中std::placeholders的使用方法》std::placeholders是C++标准库中的一个工具,用于在函数对象绑定时创建占位符,本文就来详细的介绍一下,具有一定的参考价值,感兴... 目录1. 基本概念2. 使用场景3. 示例示例 1:部分参数绑定示例 2:参数重排序4. 注意事项5.

C++11的函数包装器std::function使用示例

《C++11的函数包装器std::function使用示例》C++11引入的std::function是最常用的函数包装器,它可以存储任何可调用对象并提供统一的调用接口,以下是关于函数包装器的详细讲解... 目录一、std::function 的基本用法1. 基本语法二、如何使用 std::function

MCU7.keil中build产生的hex文件解读

1.hex文件大致解读 闲来无事,查看了MCU6.用keil新建项目的hex文件 用FlexHex打开 给我的第一印象是:经过软件的解释之后,发现这些数据排列地十分整齐 :02000F0080FE71:03000000020003F8:0C000300787FE4F6D8FD75810702000F3D:00000001FF 把解释后的数据当作十六进制来观察 1.每一行数据

urdf ( xacro ) 的 collision碰撞参数设置

目录 写在前面的话整体流程1 URDF 文件结构2 查看原始碰撞形状描述3 加入简单碰撞形状描述方法一 Meshlab 自动测量方法二 人为测量 4 加入XACRO函数简化描述 最终结果展示侧视图正视图碰撞几何体中心点设置不对出现的结果 写在前面的话 本文使用的 URDF 文件是由 solidworks 的 URDF export 插件生成,详情请看上一篇文章:solidwor

【C++学习(28)】通俗一点讲解:std::bind 回调技术

std::bind 是 C++11 标准库中的一个功能,它允许你“绑定”某些参数到一个函数、成员函数或可调用对象上,从而生成一个新的可调用对象。这种新的可调用对象可以稍后被调用,而且其中一些参数已经被预先设置好了。这在回调函数和异步编程中特别有用。 下面我用一个通俗的例子来解释 std::bind 是如何工作的。 假设场景 假设你有一个家庭厨师,他有一个技能叫做“做饭”。做饭需要两个参数:一

Rust模块std::thread

【图书介绍】《Rust编程与项目实战》-CSDN博客 《Rust编程与项目实战》(朱文伟,李建英)【摘要 书评 试读】- 京东图书 (jd.com) Rust到底值不值得学,之一  -CSDN博客 Rust到底值不值得学,之二-CSDN博客 Rust多线程编程概述-CSDN博客 12.3.2  等待所有线程完成 在前面的实例中,主线程没等到派生线程执行完毕就结束了,从而整个进程就会结束

关于std::unsorted_map和std::map

一. 前言   本文总结std库中unsorted_map和map的区别。 二. 区别示意图 mapunordered_mapOrderingincreasing order ( by default )no orderingImplementationSelf balancing BST ( like RBT )Hash TableSearch Timelog(n)average O(1)

关于std::shared_ptr和enable_share_from_this的一个隐蔽的问题

在使用共享指针时,遇到了一个如下问题: #include <iostream>class traversal;class observer {std::shared_ptr<traversal> m_tra;public:observer(std::shared_ptr<traversal> t):m_tra(t) {};~observer() { std::cout << "releas

Matlab_learning_0(linspace,std,size,ones,errorbar)

一、首先上一段代码 x=linspace(0,2*pi);y=sin(x);e=std(y)*ones(size(x)); errorbar(x,y,e,'d');%set(gcf,'MenuBar','none','Position',[400,350,350,250]); 二、函数解释        1.linsapce: linspace Linearly spac

V---机器视觉图像误判产生的因素

1.环境光 (1)图像传感器周围的光照产生的影响; (2)外接的强光产生的影响,造成图像的差异; 2.产品的个体差异 (1)产品批次变更; (2)测试时使用的样品和实际生产的产品的制作环境不同,实际生产产品有细微差异,造成干扰。 3.产品来料位置不同造成的差异 (1)假如产品移动到图像传感器视野的角落时,可能会产生形变,形变的差异造成误判。 (2)假如产品移动到图像传感器视野的不同