编译期编程

自从c++98开始,可以使用循环和路径选择执行的方式,在程序编译期执行计算。比如计算一个数是否为素数,可以使用如下的模板来实现:

template<unsigned p, unsigned d>
struct DoIsPrime
{
    static constexpr bool value = (p%d != 0) && DoIsPrime<p, d-1>::value;
};

template<unsigned p>
struct DoIsPrime<p,2>
{
    static constexpr bool value = (p%2 != 0);
};

template<unsigned p>
struct IsPrime
{
    static constexpr bool value = DoIsPrime<p,p/2>::value;
};

//call the template function
std::cout << IsPrime<9>::value << std::endl;

这里有两个问题:

  1. 为什么要声明为static?
  2. 是如何在编译期执行计算的?

先看问题1,声明为static是由于当实例化类时,类中的静态成员变量归类所有,所有对象共享统一份静态成员变量。换句话说,类特化时,不需要再定义对象即可使用该类中的静态数据。

再回答问题2,这里采用递归的方式展开计算。把展开过程梳理为:

IsPrime<9> ---> IsPrime<9,4>::value ---> 9%4 != 0 && DoIsPrime<9,3>::value ---> true && 9%3 !=0 && DoIsPrime<9,2>::value

在最后一步,由于9%3 != 0 是 false,根据经验,由前两项已经知道结果为false了,最后一个项根本不会计算,所以好像DoIsPrime<9,2>根本不会实例化。但是,这些是在编译期完成的!,因此还是会实例化。

当然还有比较清晰明了的普通函数式的写法

constexpr bool isPrime (unsigned int p)
{
    for (unsigned int d = 2; d <= p/2; ++d){
        if (p % d == 0){
            return false;
        }
    }
    return p > 1;
}

//call the template function
std::cout << isPrime(9) << std::endl;

从c++14开始,常量表达式在编译期完成计算,且支持循环等结构,不需要把所有语句在一行内完成。因此上面的函数也是在编译期完成的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值