编译期编程

简介: 编译期编程

自从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开始,常量表达式在编译期完成计算,且支持循环等结构,不需要把所有语句在一行内完成。因此上面的函数也是在编译期完成的。

相关文章
|
IDE 编译器 开发工具
编程前的准备:编译器的安装
编程前的准备:编译器的安装
57 0
|
1月前
|
XML 编译器 API
|
自然语言处理 编译器 Go
揭秘Go语言编译黑盒:从源代码到神奇可执行文件的完整过程
揭秘Go语言编译黑盒:从源代码到神奇可执行文件的完整过程
73 0
|
程序员 编译器 Linux
G0 语言编译运行说明 | 学习笔记
快速学习 G0 语言编译运行说明
|
存储 安全 编译器
基础C程序的开发和编译
基础C程序的开发和编译
基础C程序的开发和编译
|
Java 编译器 前端开发
烂尾工程: Java实现的汇编语言编译器
一个半拉子工程, 用Java实现的汇编语言编译器的介绍. 代码中使用中文命名. An unfinished project, an assembler implemented in Java, with naming in Chinese.
1171 0
|
编解码 Linux C语言
C语言编译流程
1编译流程图示 2编译各阶段命令 2-1预处理阶段 2-2 编译阶段 2-3 汇编阶段 2-4 链接阶段 3例子 1、编译流程图示 我们在Linux环境下编译单个C文件时,最简单的方法是输入一条命令gcc hello.c就可以生成默认的可执行文件a.out,展开该命令可以看到实际流程如下。
1183 0
下一篇
DataWorks