当前位置:网站首页>什么是元编程
什么是元编程
2022-08-01 13:11:00 【发如雪-ty】
元编程的英文名字是Meta Programming,也称为模板元编程,可以理解为一种编程手法,用来实现一些比较特殊的功能。元编程一般和“递归”这个词有比较密切的联系,代表着元编程这种编程手法中多数都会用到递归编程技术。
由于元编程这种手法有其特殊性,所以许多资料上会将元编程和泛型编程分开来说。其实模板编程主要应用再两个方面:1.泛型编程 2.元编程
(1)泛型编程:重点突出的是“通用”的概念,这个“泛”字就是通用的意思,程序员不需要关心具体的类型。
(2)元编程:重点突出的是一种程序设计的技巧,达到用常规的编程手段难以达到的效果。元编程可以让某些计算在编译期间完成,从而在很大程度上节约了程序运行的时间,提高程序的运行性能。
一、什么是元函数
传统的函数都是程序运行期间被调用和执行的函数,而元函数是能在编译期间被调用执行的函数(编译期间就能得到结果)。引入元函数概念的目的是支持元编程,而元函数是元编程的核心。
总结:所谓元编程,就是用元函数进行编程,甚至可以说,书写和使用这些元函数的过程本身就是在进行元编程。
c++11标准引入的constexpr关键字用于编译的时候求值,这样能够提升程序运行时的性能。
constexpr int myfun(int abc)
{
return abc*2;
}
在main函数中调用:
constexpr int var = 11*myfunc(12);
static_assert(var == 264,"sth error");
static_assert关键字是一个静态断言,是编译期间断言。如果第一个条件不满足,则提示后面的字符串。编译后没有出错。
注意:constexpr自带inline属性,这个属性是c++17标准引入的。
二、元函数分类
2.1 数值元函数
在刚才的范例,元函数myfunc()使用了constexpr关键字修饰,因为它输出的结果是一个数值,由此得名数值函数。也许有的读者可能会觉得元函数应该是个函数,其实元函数的有很多种形式,
(1)编译期间能够被调用的类模板
template<int x_v,int y_v>
struct calc
{
enum
{
addvalue = x_v + y_v,
};
};
void main()
{
const int var = calc<4, 13>::addvalue;
static_assert(var == 17, "sth error");
cout << var << endl;
system("pause");
}
结果:
随着c++语言的不断标准化,也出现了使用静态const成员变量的程序写法。所以下面的代码也是可以的:
template<int x_v,int y_v>
struct calc
{
static const int addvalue = x_v + y_v;
};
但是这样修改,可能会导致在某些情况使用了calc类模板后编译器对calc进行实例化并为addvalue分配额外的内存空间(使用enum类型的addvalue不会额外分配空间)。
再看个例子:
template<int n_v>
struct Factorial
{
enum {
value = n_v * Factorial<n_v -1>::value };
};
template<>
struct Factorial<1>
{
enum {
value = 1 };
};
void main()
{
cout << Factorial<5>::value << endl;
system("pause");
}
结果:
当n_v变为1时,编译器会实例化特化版本的Factorial,此时枚举类型的值value为1,递归结束
(2)consterpr修饰的函数
如果采用c++11的写法,那么如下:
constexpr int Factorialx(int n_v)
{
return n_v <= 1 ? 1 : (n_v * Factorialx(n_v - 1));
}
(3)constexpr修饰的变量模板
//泛化版本
template<int Arg>
constexpr int result = Arg * result<Arg - 1>;
//特化版本
template<>
constexpr int result<0> = 1;
void main()
{
cout << result<5> << endl;
system("pause");
}
2.2 类型元函数
前面介绍的都是在编译器间进行数值计算的元函数,接下来介绍编译期间类型计算的元函数。
template<typename T>
struct AddPoint
{
using type = T *;
};
void main()
{
AddPoint<const char>::type s = "I Love China!";
cout << typeid(s).name() << endl;
system("pause");
}
结果:
像AddPoint这种包含了using定义类型别名的类模板,就可以称为类型元函数,其实也就是我之前文章提到的固定萃取类模板
总结:其实在实际的编程中,元函数是一个很宽泛的概念,只要用于元编程中,在编译期间能够被调用,都可以视为元函数,不必仅限于数值元函数和类型元函数。
边栏推荐
猜你喜欢
随机推荐
软件设计师考点汇总(室内设计师个人总结)
markdown常用数学符号cov(markdown求和符号)
嵌入式开发:创建和使用可移植类型的7个技巧
Grafana 9.0 released, Prometheus and Loki query builders, new navigation, heatmap panels and more!
【每日一题】1331. 数组序号转换
使用ffmpeg来查看视频的信息,fps,和width,height
AI目标分割能力,无需绿幕即可实现快速视频抠图
DDL和DML的含义与区别「建议收藏」
Service Mesher Meetup 成都站:Service Mesh是下一代SDN吗?
LeetCode_动态规划_中等_377.组合总和 Ⅳ
JMP Pro 16.0软件安装包下载及安装教程
Simulation implementation of new of Js handwritten function
Multi-threaded cases - blocking queue
10年稳定性保障经验总结,故障复盘要回答哪三大关键问题?|TakinTalks大咖分享
VIP的实现原理
消息中间件解析 | 如何正确理解软件应用系统中关于系统通信的那些事?
JMP Pro 16.0 software installation package download and installation tutorial
如何降低Istio服务网格中Envoy的内存开销
树和二叉树的转换
Find objects with the same property value Cumulative number Summarize









