C++17中的constexpr

栏目: C++ · 发布时间: 7年前

内容简介:C++17中的constexpr

constexpr if

constexpr标记一个表达式或一个函数的返回结果是编译期常量,它保证函数会在编译期执行。相比模版来说,实现编译期循环或递归,C++17中的constexpr if会让代码变得更简洁易懂。比如实现一个编译期整数加法:

    template<int N>
    constexpr int sum()
    {
        return N;
    }
    
    template <int N, int N2, int... Ns>
    constexpr int sum()
    {
        return N + sum<N2, Ns...>();
    }

C++17之前你可能需要像上面这样写,但是现在你可以写更简洁的代码了

    template <int N, int... Ns>
    constexpr auto sum17()
    {
        if constexpr (sizeof...(Ns) == 0)
            return N;
        else
            return N + sum17<Ns...>();
    }

当然,你也可以用C++17的fold expression

    template<typename ...Args>
    constexpr int sum(Args... args) {
        return (0 + ... + args);
    }

constexpr还可以用来消除enable_if了,对于讨厌写一长串enable_if的人来说会非常开心。比如我需要根据类型来选择函数的时候:

    template<typename T>
    std::enable_if_t<std::is_integral<T>::value, std::string> to_str(T t)
    {
        return std::to_string(t);
    }
    
    template<typename T>
    std::enable_if_t<!std::is_integral<T>::value, std::string> to_str(T t)
    {
        return t;
    }

经常不得不分开几个函数来写,还需要写长长的enable_if,比较繁琐,通过if constexpr可以消除enable_if了。

    template<typename T>
    auto to_str17(T t)
    {
        if constexpr(std::is_integral<T>::value)
            return std::to_string(t);
        else
            return t;
    }

constexpr if让C++的模版具备if-else if-else功能了,是不是很酷,C++程序员的好日子来了:)

不过需要注意的是这种写法是有问题的哦。

    template<typename T>
    auto to_str17(T t)
    {
        if constexpr(std::is_integral<T>::value)
            return std::to_string(t);
        
            return t;
    }

这个代码把else去掉了,当输入如果是非数字类型的时候代码可以编译过,以为if constexpr在模版实例化的时候会丢弃不满足条件的部分,因此函数体中的前两行代码将失效,只有最后一句有效。当输入的为数字的时候就会产生编译错误了,因为if constexpr满足条件了,这时候就会有两个return了,就会导致编译错误。

constexpr if还可以用来替换#ifdef宏,看下面的例子

    enum class OS { Linux, Mac, Windows };
 
    //Translate the macros to C++ at a single point in the application
    #ifdef __linux__
    constexpr OS the_os = OS::Linux;
    #elif __APPLE__
    constexpr OS the_os = OS::Mac;
    #elif __WIN32
    constexpr OS the_os = OS::Windows;
    #endif
    
    void do_something() {
         //do something general
    
         if constexpr (the_os == OS::Linux) {
             //do something Linuxy
         }
         else if constexpr (the_os == OS::Mac) {
             //do something Appley
         }
         else if constexpr (the_os == OS::Windows) {
             //do something Windowsy
         }
    
         //do something general
    }
    //备注:这个例子摘自https://blog.tartanllama.xyz/c++/2016/12/12/if-constexpr/

代码变得更清爽了,再也不需要像以前一样写#ifdef那样难看的代码块了。

constexpr lambda

constexpr lambda其实很简单,它的意思就是可以在constexpr 函数中用lambda表达式了,这在C++17之前是不允许的。这样使用constexpr函数和普通函数没多大区别了,使用起来非常舒服。下面是constexpr lambda的例子:

    template <typename I>
    constexpr auto func(I i) {
      //use a lambda in constexpr context
      return [i](auto j){ return i + j; }; 
    }

constexpr if和constexpr lambda是C++17提供的非常棒的特性,enjoy it.

Post Views: 6


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Realm of Racket

Realm of Racket

Matthias Felleisen、Conrad Barski M.D.、David Van Horn、Eight Students Northeastern University of / No Starch Press / 2013-6-25 / USD 39.95

Racket is the noble descendant of Lisp, a programming language renowned for its elegance and power. But while Racket retains the functional goodness of Lisp that makes programming purists drool, it wa......一起来看看 《Realm of Racket》 这本书的介绍吧!

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

html转js在线工具
html转js在线工具

html转js在线工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试