元编程结构控制

来源:互联网 发布: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 编辑器,无序列表格式全丢

原创粉丝点击