跟我学c++中级篇——c++17之constexpr if

文章介绍了C++中的constexpr关键字及其在模板元编程中的作用,特别是constexprif的引入,作为编译期的条件分支控制,简化了enable_if等技术的使用。通过示例展示了constexprif如何简化代码并提高编译时的效率。文章还讨论了constexprif的限制和应用场景,强调了深入理解基础知识的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、constexpr

在前文对const的几种形式进行了分析说明,但是constexpr if的应用没有顾及到。在模板元编程constexpr可以起到一种类似于if else的作用。毕竟不管在哪里运行,哪个时期运行,条件判断总是需要的。在早期的模板编程中,如果想做这种判断需要使用常见的如enable_if之类的模板,特别是c++的灵活性会产生一些代码,它不符合c++的规范(即不推荐这么写),但又被编译使用(c++又支持),这种情况被称做ill-formed
,如果是类型则ill-formed type,cppreference称之为非良构类型。
这就又回到前面提到的SFINAE和Concepts,而在模板板的元编程里这又一是种强需求,所以以这条线来看c++标准的迭代,就会看到,对类似的支持是越来越完善。明白了这些,再回头学习和应用constexpr if就会有的放矢,知其然,并知其所以然。

二、constexpr if

先看一个例子,来理解constexpr if:

//C++17以前
template <typename T>
std::enable_if_t<std::is_integral<T>::value, std::string>
 to_string(T t){
   return std::to_string(t);
 }
 ​
template <typename T>
std::enable_if_t<!std::is_integral<T>::value, std::string>
 to_string(T t){
   return t;
 }
//c++17以后
template <typename T>
auto to_string(T t) {
   if constexpr(std::is_integral<T>::value) {
     return std::to_string(t);
   } else {
     return t;
   }
 }

一般来说,在模板中进行分支控制主要有以下几种情况,一个是采用偏特化机制,对不同的类型参数输入产生不同的结果,这个在前面的false_type中就有体现;另外一个是使用std::enable_if_t来实现;然后就是今天分析的constexpr if。在编译器控制分支的情况下,在c++17以前,无论哪种分支,都是会被编译的,但是在c++17后,不会控制到的则不会编译,不过虽然如此,另外的分支仍然要符合c++的语法,否则仍然是无法编译通过。
上面这个例子把偏特化的例子省略了,其实从模板元编程的角度看,就是对SFINAE技术的一个优化和简化的过程。把这些基本的情况了解后,回头再看constexpr if就会有一个比较深刻的理解。
然后来分析一下它的定义:constexpr if是一种在编译期进行分支控制的写法,constexpr可以紧跟在if的后面。通过对条件块中不满足的部分直接处理掉,但是这有一个前提,这个条件块必须是一个常量表达式并且可以显示的转换成布尔值。

三、应用

前面提到过constexptr if主要是对模板元编程的支持,它能够起到让代码更直观,更简便,使得在编译期内的元编程不再像SFINAE那样晦涩。下面再看一个数列的计算:

#pragma once
template<long N>
constexpr long Fib() {
    if constexpr (N >= 2) {
        return Fib<N - 1>() + Fib<N - 2>();
    }
    else {
        return N;
    }
}

void TestFib() {
    static_assert(Fib<0>() == 0);
    static_assert(Fib<1>() == 1);
    static_assert(Fib<2>() == 1);
    static_assert(Fib<3>() == 2);
}
int main()
{
    TestFib();
    return 0;
}

这个例子没有判断值的范围,但是这里重点是讲constexpr if的用法,所以不必太再乎这个。是不是非常简单,它和印象中在执行期运行的代码已经长得很像了。
使用constexpr if优点不少,它可以减少代码的编译生成数量,也可以更简洁是了,但它也不少的受限情况:比如函数和运行期类似,在某些情况下没有写constexpr仍然可以运行,而这种运行则无法在编译期优化了。同时,其多多类型返回无能为力。所以在实际应用中,还是要小心为妙。
总体来看,constexpr if的应用场景还是很受限的,它只能放在一般意义的函数内部,如果必须需要减小编译出的代码文件的大小,尽量减少依赖资源,它还是有可能施展身手的。更具体的情况需要开发者根据需要来确定它的应用。

四、总结

constexpr的详细用法不同版本都在网上有详细的说明,但如何能更好的在何处使用它,这才是一个比较让人头疼的问题。正如上学一样,老师一讲就明白,自己做题就糊涂。如何打破这个怪圈,就需要从基础入手,反复把基础的知识吃透,然后再结合例程自己不断修改完善,才有机会冲出桎梏,解放思想。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值