模板元编程(英语:Template metaprogramming;缩写:TMP)是一种元编程技术,不夸张的说,这项技术开启了一种新的C++编程方式。编译器使用模板产生暂时性的源码,然后再和剩下的源码混合并编译。这些模板的输出包括编译时期常数、数据结构以及完整的函数。如此利用模板可以被想成编译期的运行。本文介绍了利用模板元编程技术实现在编译期判断一个整数是否为素数的算法。输入为一个大于0的整数,输出为1表示该整数为素数,为0表示为合数。本文的主要目的是用实例说明模板元编程实现算术和逻辑运算的一般设计和编写方法。模板元编程的概念和基本介绍参见维基百科:http://zh.wikipedia.org/wiki/模板超編程

我们使用最基本的素数判断算法,伪代码如下:

function IsPrime(n)
if n == 1 then return false
if n == 2 then return true
for each m from 2if m * m > n then return trueif n mod m = 0 then return falsem := m + 1

这显然是一个复杂度为O(sqrt(n))的算法,主要的逻辑为循环。模板元编程是以递归的逻辑形式来实现循环算法,因此必须先明确两件事:有几个变量参与,以及循环的终止条件是什么。这个算法显然有2个变量参与运算:一个是n,另一个是m。我们令m从2开始递增,直到达到循环终止条件。在模板元编程中,由于模板参数推导的优先级是以特化程度排列的,因此终止条件和特殊值的处理使用偏特化(也叫部分特化)实现。关于模板参数推导和偏特化的概念和语法这里不做赘述,请参阅C++书籍或搜索网页资料。那么根据以上分析,我们可以先写出一个框架如下:

template<uint n, uint m>struct TEST{const static uint r = TEST<n, nextM>::r; //nextM为下一个M,暂不实现。在这里用递归结构代替了循环
};
template<uint n>struct ISPRIME{const static uint r = TEST<n, 2>::r; //从2开始,依次判断每一个可能的m取值,判断代码暂未实现。
};
template<>struct ISPRIME<1>{ //对于算法不能计算的特殊值1,判断为0const static uint r = 0;
};
template<>struct ISPRIME<2>{ //对于算法不能计算的特殊值2,判断为1const static uint r = 1;
};

循环的终止条件是:m的平方大于n或可以整除n。当满足终止条件时,向模板参数传递一个特殊值,并在偏特化中处理这个值,那么递归逻辑就终止了。而判断是否满足终止条件,则需进行逻辑和算术运算。基于以上分析,框架代码改写如下:

template<uint n, uint m>struct TEST{// if (n % m == 0) n = 0;// if (m * m > n) m = 0; else ++m;const static uint r = TEST<n, m>::r; //上面两行代码不能写在此处,仅说明逻辑。实际的语法下文再做介绍
};
template<uint m>struct TEST<0, m>{ //n为0的情况const static uint r = 0; //即在非特化的模板代码中,n可以被m整除,因此n被赋值为0,故为合数
};
template<uint n>struct TEST<n, 0>{ //m为0的情况const static uint r = 1; //即在非特化的模板代码中,m * m > n,因此n不能被任何比它小的数整除,故为素数
};
template<uint n>struct ISPRIME{const static uint r = TEST<n, 2>::r; //从2开始,依次判断每一个可能的m取值,判断代码暂未实现。
};
template<>struct ISPRIME<1>{ //对于算法不能计算的特殊值1,判断为0const static uint r = 0;
};
template<>struct ISPRIME<2>{ //对于算法不能计算的特殊值2,判断为1const static uint r = 1;
};

最后只要用模板的参数推导实现取模的算术运算和上面框架中的两个逻辑判断即可,完整代码如下:

#include <iostream>
typedef unsigned int uint;template<uint n, uint m>struct NEXTN{const static uint r = ((n % m != 0) * n);
};template<uint n, uint m>struct NEXTM{const static uint r = (m * m <= n ? (m + 1) : 0);
};template<uint n, uint m>struct TEST{const static uint r = TEST<NEXTN<n, m>::r, NEXTM<n, m>::r>::r;
};template<uint m>struct TEST<0, m>{const static uint r = 0;
};template<uint n>struct TEST<n, 0>{const static uint r = 1;
};template<uint n>struct ISPRIME{const static uint r = TEST<n, 2>::r;
};template<>struct ISPRIME<1>{const static uint r = 0;
};template<>struct ISPRIME<2>{const static uint r = 1;
};int main()
{int primes[] = {ISPRIME<1>::r, ISPRIME<2>::r, ISPRIME<3>::r, ISPRIME<4>::r,ISPRIME<5>::r, ISPRIME<6>::r, ISPRIME<7>::r, ISPRIME<8>::r,ISPRIME<9>::r, ISPRIME<10>::r, ISPRIME<11>::r, ISPRIME<12>::r,ISPRIME<13>::r, ISPRIME<14>::r, ISPRIME<15>::r, ISPRIME<16>::r,};for (int i = 0; i < sizeof(primes) / sizeof(primes[0]); ++i)std::cout << i + 1 << (primes[i] ? " YES" : " NO") <<std::endl;return 0;
}

如果您有更简洁的写法,请回复告知。谢谢!

转载于:https://www.cnblogs.com/devymex/p/3326793.html

模板元编程实现素数判定相关推荐

  1. C++高阶必会操作--模板元编程

    泛型编程大家应该都很熟悉了,主要就是利用模板实现"安全的宏",而模板元编程区别于我们所知道的泛型编程,它是一种较为复杂的模板,属于C++的高阶操作了,它最主要的优点就在于把计算过程 ...

  2. C++ 模板元编程简介

    文章目录 1.概述 2.模板元编程的作用 3.模板元编程的组成要素 4.模板元编程的控制逻辑 4.1 if 判断 4.2 循环展开 4.3 switch/case 分支 5.特性.策略与标签 6.小结 ...

  3. 最好的 C++ 模板元编程干货!

    链接 | https://www.cnblogs.com/liangliangh/p/4219879.html 所谓元编程就是编写直接生成或操纵程序的程序,C++ 模板给 C++ 语言提供了元编程的能 ...

  4. 编程实现算术表达式求值_用魔法打败魔法:C++模板元编程实现的scheme元循环求值器...

    本文使用 Zhihu On VSCode 创作并发布 [TOC] 前言 寒假时沉迷C++模板元编程,写了个简单的Scheme元循环求值器.可以用类似Scheme的语法写出这样的C++模板代码: _&l ...

  5. C++用模板元编程进行循环展开的性能测试

    在网上看到一篇C++模板元编程的文章,里面提到可以用来做循环展开,文章地址如下: https://www.2cto.com/kf/20120... 然后在VS2015里测了一下,测试代码如下: tem ...

  6. C++模板元编程 入门简介

    最近一直在看STL和Boost,源码里边好多涉及到模板元编程技术,简单了解一下,备忘(Boost Python中的涉及模板元的部分重点关注一下). 范例引入 // 主模板 template<in ...

  7. xpath里面if判断一个值不为空_现代C++之模板元编程(今天写个If与While)

    现代C++之模板元编程(今天写个If与While) 0.导语 今天就放轻松,有可能代码写的看的很晦涩,自己多敲几遍即可,下面来进入正文,如何使用模板元编程实现IF与WHILE. 1.IF实现 我们想要 ...

  8. 现代C++模板元编程基础

    元函数的基础介绍 C++的模板元编程是函数式编程,所以函数是一等公民.一切在编译期间执行的函数都可以称为元函数.元函数有struct和constexpr两种定义方式,前者是一直使用的,后者是C++11 ...

  9. 跟我学c++高级篇——模板元编程之十一鸭子类型

    一.鸭子类型 鸭子类型不是从c++中出现的,duck typing这种称呼在Python中比较多见.那么什么是鸭子类型呢?它是动态类型的一种风格,只要是对象的特征(其方法和属性集)和某个类型一致,就认 ...

最新文章

  1. 针对还没搞懂javascript中this关键字的同学
  2. eeglab中文教程系列(6)-数据叠加平均{1}(Data averaging)
  3. linux 连接远程命令行,screen命令行远程连接
  4. Hadoop 1.2.1 集群安装一
  5. Silverlight 3D开源项目,取材于CodePlex和微软的开源项目,主要是更新至Silverlight RTM版...
  6. 转【FullPage.js 应用参数参考与简单调用】
  7. 【bzoj1738】[Usaco2005 mar]Ombrophobic Bovines 发抖的牛 Floyd+二分+网络流最大流
  8. windows系统改装为linux系统_Linux怎么克隆系统?备份系统跟Windows系统有区别吗?...
  9. TypeScript 类(Class)
  10. const指针和指向const对象的指针
  11. C++之文件操作探究(一):写文件——文本文件
  12. Linux 查看命令
  13. day 15 模块、起别名、from导入
  14. CentOS之安装docker
  15. vue-cli的项目中关于axios的全局配置,结合element UI,配置全局loading,header中做token传输...
  16. 语录(心灵鸡汤来一波)
  17. 猿辅导 iOS 精准测试实践 - Objective-C 与 Swift 混编工程精准测试探索
  18. 三国历史上最不该被埋没诋毁的十大人才
  19. 【代码重构】临时字段(Temporary Field)-- 如何消除和处理代码中临时字段
  20. 智课雅思词汇---二十七、形容词后缀-ant/-ent

热门文章

  1. 13个风格独特的关于页面(About Pages)设计
  2. 使用VS2012进行性能测试和负载测试
  3. 21.使用委托表达回调
  4. 为什么说Lucene不好
  5. Promise 的使用
  6. cmake用法及常用命令总结(全)
  7. springMVC文件下载
  8. 静态页面访问缓慢的问题
  9. Android studio中正确引入so文件的方法
  10. 如何让自己的收件箱只收到自己订阅的邮件服务商