暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

C++17中的constexpr

purecpp 2017-06-12
661

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还可以用来消除enableif了,对于讨厌写一长串enbaleif的人来说会非常开心。比如我需要根据类型来选择函数的时候:

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;
}

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

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提供的非常棒的特性,enjoin it.

文章转载自purecpp,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论