C++模板元编程和编写模板有什么区别?

C++模板元编程和编写模板有什么区别?什么是模板元编程?应用场景主要有哪些?

很多回答都是复制粘贴一段没有什么用处的。我来说几句,如果lz满意,希望采纳,鼓励下诚实原创的回答。如果不满意,欢迎追问。

模板元编程的意思是使用模板实现元编程,它的内涵比模版本身(java称为泛型)大得多。模版可以看作元编程最基本的运用。
所谓元编程,就是编写一个用来编程的程序(生成代码的程序),元xx(英文meta-xxx)就是xxx的xxx。比如,元学习就是学习如何学习的方法,元数据就是描述数据的数据,等等。

C++的模版之所以可以用来作为代码生成器,是因为它是图灵完备的,也就是说,它可以实现一切编程语言能实现的功能,关键的一条是,C++的模版可以定义参数变量。而不仅仅是类型。
比如
计算1+2+3...+100
我们可以不用循环,只用递归实现,那就是
给定一个n=100,我们可以让机器生成如下代码:
int sum_n_1()
{
return 100 + sum_n_2();
}
注意sum_n_2这个函数也不存在,但是我们可以继续生成这么一个函数
int sum_n_2()
{
return 99 + sum_n_3();
}
...
直到生成一个
int sum_n_100()
{
return 1;
}
那么要计算1+2+3...+100,如果机器生成了以上100个函数,我们只要调用sum_n_1()是不是就算出来了呢?
这个过程关键是这100个函数,是自动生成的,而不是我们自己一个一个写的。用C++模版得到如下代码:

 #include <iostream>

template<typename T, int i=1>
class someComputing {
public:
    typedef volatile T* retType; // 类型计算
    enum { retValume = i + someComputing<T, i-1>::retValume }; // 数值计算,递归
    static void f() { std::cout << "someComputing: i=" << i << '\n'; }
};
template<typename T> // 模板特例,递归终止条件
class someComputing<T, 0> {
public:
    enum { retValume = 0 };
};

template<typename T>
class codeComputing {
public:
    static void f() { T::f(); } // 根据类型调用函数,代码计算
};

int main(){
    someComputing<int>::retType a=0;
    std::cout << sizeof(a) << '\n'; // 64-bit 程序指针
    // VS2013 默认最大递归深度500,GCC4.8 默认最大递归深度900(-ftemplate-depth=n)
    std::cout << someComputing<int, 500>::retValume << '\n'; // 1+2+...+500
    codeComputing<someComputing<int, 99>>::f();
    std::cin.get(); return 0;
}

就可以实现生成代码的功能。
因为这个过程完全是编译器做的,所以最后生成的计算1+2+3...+100
会自动展开函数,得到5050,也就是结果。
那么显然当程序运行的时候,直接就输出结果了,程序不需要再求和。求和的过程提前到编译阶段就完成了。

我们可以用解释语言来类比:
解释语言实现了运行的时候编译
元编程实现了编译的时候运行。

所谓模板元编程就是编写直接生成或操纵程序的程序,C++ 模板给 C++ 语言提供了元编程的能力,模板使 C++ 编程变得异常灵活,能实现很多高级动态语言才有的特性(语法上可能比较丑陋,一些历史原因见下文)。普通用户对 C++ 模板的使用可能不是很频繁,大致限于泛型编程,但一些系统级的代码,尤其是对通用性、性能要求极高的基础库(如 STL、Boost)几乎不可避免的都大量地使用 C++ 模板,一个稍有规模的大量使用模板的程序,不可避免的要涉及元编程(如类型计算)

例如将两个变量交换的函数swap;
如果不是用模板的话我们需要针对不同的类型写很多个功能相同的函数,例如int、char等等
而使用模板的话则只用使用一个函数就足够了
template
void swap(T a, T b);
调用的时候可以显示的说明类型例如:swap(3, 5)
也可以使用简单的用法,和使用普通函数是一样的:swap(3, 5)
更具体的你可以自己查阅相关资料

可参考链接:https://www.1688.com/ask/76e3fbdc-e9a5-449c-b291-ac89cb86a900.html

模板元就是利用模板语法写代码,把需要编译好在内存中动态计算的数据在编译器就搞定了,这个代码将会有编辑器进行计算。看完和掌握差的很远的。先学别的吧,模板元编程用的不多吧,反正我学了两年多了一种没看这个。编程这是每个游戏相关信息编程FAQ里都有的问题。这个问题每星期都会在游戏开发论坛上被问上好几次。这是个很好的问题,但是,没人能给出简单的答案。在某些应用程序中,总有一些计算机语言优于其他语言。希望这篇文章能帮助你做出决定。C语言如果说FORTRAN和COBOL是第一代高级编译语言,那么C语言就是它们的孙子辈。C语言是Dennis Ritchie在七十年代创建的,它功能更强大且与ALGOL保持更连续的继承性,而ALGOL则是COBOL和FORTRA。建立通用的设计库,提供给用户使用。

模板元编程其实是通过编译时编译器的运算来减轻运行时负担,提高程序可靠性和辅助简化代码的实现。

模版元编程(template metaprogram)是C++中最复杂也是威力最强大的编程范式,它是一种可以创建和操纵程序的程序。模版元编程完全不同于普通的运行期程序,它很独特,因为模版元程序的执行完全是在编译期,并且模版元程序操纵的数据不能是运行时变量,只能是编译期常量,不可修改,另外它用到的语法元素也是相当有限,不能使用运行期的一些语法,比如if-else,for等语句都不能用。因此,模版元编程需要很多技巧,常常需要类型重定义、枚举常量、继承、模板偏特化等方法来配合,因此编写模版元编程比较复杂也比较困难。

  现在C++11新增了一些模版元相关的特性,不仅可以让我们编写模版元程序变得更容易,还进一步增强了泛型编程的能力,比如type_traits让我们不必再重复发明轮子了,给我们提供了大量便利的元函数,还提供了可变模板参数和tuple,让模版元编程“如虎添翼”。本文将向读者展示C++11中模版元编程常用的技巧和具体应用。

从我的经验来看,C++的模板元编程(TMP)的基本原则就是:将负载由运行时转移到编译时,同时保持原有的抽象层次。其中负载可以分为两类,一类就是程序运行本身的开销,一类则是程序员需要编写的代码。前者可以理解为编译时优化,后者则是为提高代码复用度,从而提高程序员的编程效率。我在实际工作中使用到的TMP举例如下:1) 使用TMP进行loop unrolling 其中模板的参数决定了循环的长度。这个技术是很多地方都有用到的 我是在用CUDA写device端的程序时即需要利用loop unrolling优化,又想保留一个方便的接口在调试时修改,所以才用TMP。2) 使用functor和operator将逻辑操作和实际运算分开,提高开发新算法的效率。比如如果一个新的算法可以复用operator,那么就编写新的functor作为模板参数传进去。基本上任何基于模板的算法库都会采用这种策略来提高代码复用率,比如boost。3) 静态的多态。很多时候多态里子类的类型都是编译时可确定的,这时候采用通常的多态构造虚函数表其实是增加了运行时开销,利用模板将子类类型名作为模板参数放到父类里即可将运行时的负载转换为编译时负载。将TMP运用到极致的库叫做Loki[1],我本人完全没用过,但阅读其中的代码可以加深对TMP的理解。另外,它里面提倡的policy-based design我在工作中经常使用。当然,我感觉采用TMP的工业级代码还是相当少的,因为第一是冗长的编译时间开销会让一些调试和开发变得效率低下,另外TMP也会一定程度上降低程序的可读性。

模板编程包含元编程,元编程只是名字看起来很可怕而已,不过就是模板编程。元编程同普通编程相比就是思考方式需要改变一下,循环用递归,判断用特化仅此而已。例如

模板求任意个任意元素的最大值

补充,可以实现一些传统编程方式没法实现的操作,比如判读一个对象有没有某种成员函数,有就调用,没有就用其它可能的代替方法,只能通过元编程实现,而传统方式编译通不过。