当前位置:网站首页>什么是元编程
什么是元编程
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定义类型别名的类模板,就可以称为类型元函数,其实也就是我之前文章提到的固定萃取类模板
总结:其实在实际的编程中,元函数是一个很宽泛的概念,只要用于元编程中,在编译期间能够被调用,都可以视为元函数,不必仅限于数值元函数和类型元函数。
边栏推荐
猜你喜欢
芝加哥丰田技术学院 | Leveraging Natural Supervision for Language Representation Learning and Generation(利用自然监督进行语言表示学习和生成)
leetcode: 1201. Ugly Number III [Dichotomy + Mathematics + Inclusion and Exclusion Principle]
Beyond Compare 4 trial period expires
MCU开发是什么?国内MCU产业现状如何
【5GC】5G网络切片与5G QoS的区别?
shell 中的 分发系统 expect脚本 (传递参数、自动同步文件、指定host和要传输的文件、(构建文件分发系统)(命令批量执行))
如何使用 Authing 单点登录,集成 Discourse 论坛?
Apex installation error
PAT1166 Summit(25)
Qt实战案例(56)——利用QProcess实现应用程序重启功能
随机推荐
【无标题】
脚本语言Lua的基础知识总结
How does the SAP ABAP OData service support the Create operation trial version
如何使用OpenCV测量图像中物体之间的距离
一文带你读懂云原生、微服务与高可用
Detailed explanation of table join
207.数组序号转换
MVVM响应式
快速理解拉格朗日乘子法
mysql的基本使用
使用ffmpeg来查看视频的信息,fps,和width,height
线上问题排查常用命令,总结太全了,建议收藏!!
计算器:中缀表达式转后缀表达式
JMP Pro 16.0 software installation package download and installation tutorial
Batch replace tables in Word with pictures and save
Do wildcard SSL certificates not support multiple domains?
How to integrate 3rd party service center registration into Istio?
安全又省钱,“15岁”老小区用上管道燃气
8. How does the SAP ABAP OData service support the Create operation
Feign 从注册到调用原理分析