元编程结构控制
来源:互联网 发布:python写入excel 编辑:程序博客网 时间:2024/06/06 16:28
- 前言
- 什么是元编程
- 模板推导
- 斐波那契数列
- 结构控制
- 线性结构
- 分支结构
- if 分支
- if else 分支
- 循环结构
- 实例
前言
元编程,听上去是一个高大上的词语。没错,它就是一个高大上的词语,它代表了 C++ 中最黑的黑科技,没有之一。
你知道编译期可以做什么吗?你想让编译器帮你计算什么吗?你想用你的程序去操纵程序吗?你知道在 C++ 这种静态语言中藏着一种函数式的动态脚本语言吗?你想榨干编译器最后一点点节操吗?
坑深慎入!
什么是元编程
元编程,全称模板元编程。
元编程(Metaprogramming)是指某类计算机程序的编写,这类计算机程序编写或者操纵其他程序(或者自身)作为它们的数据,或者在运行时完成部分本应在编译时完成的工作。很多情况下与手工编写全部代码相比工作效率更高。编写元程序的语言称之为元语言,被操作的语言称之为目标语言。一门语言同时也是自身的元语言的能力称之为反射。
以上词条来自百度百科
当然,如果不想看这么专业的解释的听我说:(深吸一口气)
元编程是利用编译器在编译期强大的模板推导能力去进行计算的编程形式。
先放一段代码让你知道什么叫强大的推导能力,可能学过编译原理的人能更懂我说的这是什么:
int main() { const int i = 1; const int j = 2; int k = i + j; return 0;}
我告诉你,在编译期,k 的值就是3,因为这里编译器在编译期就已经帮你计算好了,而不是在运行期再进行计算。
至于究竟是不是这么回事,我也没验证过,我想表达的就是这个意思。
模板推导
熟悉模板的人应该都知道,C++ 的模板参数都是在编译期推导出来的,它大概是怎么一种过程:
编写模板程序 -> 编译期带入相应的参数 -> 编译期生成相应的函数或类 -> 运行期执行相应的函数或类
比如下面这段代码:
template <typename T>void function(T value) { ...}int main() { function<int>(2);}
在编译期匹配函数签名 function,发现这是个模板函数,于是将 int 带入到模板参数中去,编译期生成了一个新的函数:
void function(int value) {}
是不是很像宏?但是它比宏更安全,它并不是简单的替换,而是类型安全的,因为它有类型推到的过程,如果出错,就是编译期错误。
斐波那契数列
模板元编程已经被证明是图灵完备的了,所以它理论上可以编写任何东西,参考 Boost::mpl 库。
一开始接触元编程,最典型例子就是编译期斐波那契数列:
template <int N>struct Fibonacci { enum { value = Fibonacci<N-1>::value + Fibonacci<N-2>::value; };};template <>struct Fibonacci<1> { enum { value = 1; };};template <>struct Fibonacci<0> { enum { value = 0; };};int main() { cout << Fibonacci<5>::value << endl; // output: 5}
看不懂?我给你解释一下:
编译期,会将 Fibonacci<5>::value
展开成 Fibonacci<5>::value = Fibonacci<4>::value + Fibonacci<3>::value
,然后后面两个继续展开,直到展开为0和1两种情况。
int main() { // 展开一次 cout << Fibonacci<4>::value + Fibonacci<3>::value << endl; // output: 5 // 展开两次 cout << Fibonacci<3>::value + Fibonacci<2>::value + Fibonacci<2>::value + Fibonacci<1>::value << endl; // output: 5 // 展开三次 cout << Fibonacci<2>::value + Fibonacci<1>::value + Fibonacci<1>::value + Fibonacci<0>::value + Fibonacci<1>::value + Fibonacci<0>::value + Fibonacci<1>::value << endl; // output: 5} // 展开四次 cout << Fibonacci<1>::value + Fibonacci<0>::value + Fibonacci<1>::value + Fibonacci<1>::value + Fibonacci<0>::value + Fibonacci<1>::value + Fibonacci<0>::value + Fibonacci<1>::value << endl; // output: 5 // 展开五次 cout << 1+0+1+1+0+1+0+1 << endl; // 推导结果 cout << 5 << endl;
是不是很强大?
结构控制
结构:线性结构、分支结构、循环结构
线性结构
在元编程中,线性结构和非元编程是一样的
分支结构
if 分支
template <bool condition>struct If {};template <>struct If<true> { enum { value = 1; }; static void function() { cout << "true condition" << endl; }};template <>struct if<false> { enum { value = 0; }; static void function() { cout << "false condition" << endl; }};
由主模板 If 特化出两个模板,一个是 true 的特化,一个是 false 的特化,想在里面做什么就直接说吧。
int main() { cout << If<(2 == 3)>::value << endl; // output: 0}
if else 分支
template <bool condition, typename True, typename False>struct IfElse { typedef True result;};template <typename True, typename False>struct IfElse<false, True, False> { typedef False result;};
现在带条件的 IfElse。
IfElse<(1+1 == 2), char, int>::TypeResult result1;cout << "if result is int:" << (typeid(result1) == typeid(int)) << endl;cout << "if result is char:" << (typeid(result1) == typeid(char)) << endl;
循环结构
在元编程中,循环结构一般是通过递归调用来体现的,就像斐波那契数列中那样子,以两个特化模板作为递归终止。
实例
用序列求和做一个简单的实例:
// 编译期序列求和// 主模板template <int N>struct Sum { static const int nResult = Sum<N-1>::nResult + N;};// 特化递归终止模板template <>struct Sum<0> { static const int nResult = 0;};// 测试序列求和void testMP_Sum() { cout << "Sum<10>::nResult:" << Sum<10>::nResult << endl;}
CSDN 辣鸡 MD 编辑器,无序列表格式全丢
- 元编程结构控制
- shell编程基础---控制结构
- C++template元编程学习心得-switch结构
- Python元编程:控制你想控制的一切
- Shell编程(三)---控制结构及函数
- 结构化编程:跳转控制break、continue
- PL/SQL编程整理3 -- 控制结构
- 控制流结构--shell编程笔记
- 《精通Oracle10gPLSQL编程》7、编写控制结构
- Shell编程之控制结构if
- Scala控制结构、函数式编程解析
- c++编程思想2 --友元存储控制
- 宏元编程—逻辑控制——实现分支
- 元编程
- 元编程
- 元编程
- Chap 6 学习笔记-控制结构和过程式编程
- 结构化编程:确定迭代循环控制for
- 线程终止的方法
- Valid Triangle Number (第十六周 数组)
- 开源派
- JAVA 基础定义 day1
- 微信小程序实战篇-下拉刷新与加载更多
- 元编程结构控制
- python及scikit-learn的安装
- fastjson 使用 string字符串转换成java的各种类型
- 元编程算法示例
- 电商平台静态资源(图片)一般及CDN解决方案(转载)
- 机器学习并行化(parallel machine learning)
- CentOS-5的yum源无法使用问题
- 静态库 .a 转成共享库 .so
- 九度 题目1350:二叉树的深度