【C++ Metaprogramming】0. 在C++中实现类似C#的泛型类

两年前,笔者因为项目原因刚开始接触C++,当时就在想,如果C++有类似C#中的泛型限定就好了,能让代码简单许多。我也一度认为:

虽然C++有模板类,但是却没办法实现C#中泛型特有的 where 关键词:

public class Parent { /* ... */ }
public class Child : Parent { /* ... */ }
public class AnotherClass { /* ... */ }

public class GenericClass<T> where T : Parent 
{
	public static void DoSomething(T item) { }
}

static void Main(string[] args)
{
	Child c = new Child();
	AnotherClass a = new AnotherClass();
	GenericClass<Parent>.DoSomething(c);
	GenericClass<Child>.DoSomething(c);
	GenericClass<AnotherClass>.DoSomething(); // --- 报错
}

但实际上,C++通过不仅能做到这部分内容,而且比C#能做的还要更多。而且很多内容甚至是可以在Compile Time就能做到限制的 —— 不用等到代码跑起来,编译的时候就能够告诉你代码哪里有问题。

C++实现这部分功能所涉及到的技术就是 Metaprogramming,直译过来是“元编程”。

我相信 元编程 这个名字对于大多数人来说是没有意义的,就好像我们第一次听到某种深海动物名字一样,它叫什么不重要,重要的是,它是什么。

比如我现在向大家介绍一种深海动物,“须蛸”。如果我不放这个图,“须蛸”这个名字就是没有任何意义的 (放了这图似乎也没多大意义,但是至少你更加信服这个名字不是我瞎编的了)。
在这里插入图片描述
所以什么是元编程?


元编程是对代码的编程


元编程英文里的Meta可以认为是“超级”的意思,这里的“超级”应该不是指“能力强过、高过”,亦不是说“凌驾于xxx之上”的意思。

在我个人理解里,Metaprogramming技术本身并非高明于我们平时的普通编程技术,它只是思维方式不一样。但不幸的是,C++的Metaprogramming是一只披着C++语言外皮的“狼”(需要完全用另一套思维逻辑去思考/实现的另一个编程领域),所以笔者认为这也是为什么许多C++用了许多年的人谈到Metaprogramming这个领域时仍噤若寒蝉——因为它们压根不是一个东西,只是恰好语法底层用到的是同一套东西而已——而且在实际工作中你可以完全不使用该内容而写好自己的代码(只不过在某些情况可能要多付出一点体力劳动……不过有Vim在,那也不是什么大问题嘛)。

说到Meta的“超级”的含义,Metaprogramming在我这里十分像优化领域里的Hyperparameter Optimization (超参数优化)里的“Hyper” —— 同样是“超级”的意思,同样的,超参数优化也不是说它本身相较于普通的参数优化有什么更深奥的技术,只不过是Optimization的参数的Optimization,优化参数的优化,所以就用差不多的技术在对不同的目标套了一层。

在这里插入图片描述
巧了么不是,Metaprogramming是对普通programming的programming,我觉得起名叫Hyperprogramming也是挺不错的。而且他俩都有一个共同点,那就是特别烧脑,都要在原有的概念上嵌套一层。

好了,说了这么多,那倒底啥是Metaprogramming?下面就举个简单的例子,我们用C#来实现它,简单说说啥是Metaprogramming。


什么是Metaprogramming


现在我们要写个程序,需求是:

能够返回正整数1-5的平方。

普通编程的方法是:

int ReturnSquare(int i) => i * i;

Metaprogramming的方法是:
写一个Console程序,输出一个cs文件:

static void Main(string[] args)
{
	using var fs = File.Create("d:\square.cs", FileMode.Create);
	using var sr = new StreamWriter(fs);
	sr.AppendLine("int ReturnSquare(int i) => i * i");
	sr.Flush();
}

这就是Metaprogramming。


???


是的,这就是Metaprogramming。


不过这只是最广义上的概念,但这个概念的确如此 —— 用代码去写代码。这个技术就是Metaprogramming。

我们一般说C++的Metaprogramming是指 “使用C++的模版技术来借助编译器在编译时帮我们生成、检查代码”

笔者这里再插一段,C#也是有模版的,也是需要借助编译器才可以,感兴趣的读者可以自行搜索“C# Text Template”,或者官方链接:
https://learn.microsoft.com/en-us/visualstudio/modeling/code-generation-and-t4-text-templates?view=vs-2022

对于Metaprogarmming的介绍今天就先到这里了,后面有想到的会继续补充,下面的时间留给标题里的内容。

我是被标题吸引的,我要C++实现泛型限定

  1. 限定Parent
#include <type_traits>

class Parent{};
class Child : public Parent{};
class AnotherClass {};

namespace hidden {
	template <bool b, typename T>
	struct Helper
	{
		static void DoSomething(T item) = delete;
	};
	template <typename T>
	struct Helper<true, T>
	{
		static void DoSomething(T item)
		{
			// ...
		}
	};
}

template <typename T>
using Generic = hidden::Helper<std::is_base_of_v<Parent, T>, T>;

int main()
{
	Child c;
	AnotherClass a;
	Generic<Parent>::DoSomething(c);
	Generic<AnotherClass>::DoSomething(a); // -- 报错
}
  1. 限定 “类里必须要有Foo函数” 才可使用

// 具备成员函数Foo
class HasFoo
{
public:
	int Foo();
};

// 不具备成员函数Foo,仅有静态函数Foo
class StaticFoo
{
public:
    static int Foo();
};
// 啥也没有
class NoFoo { };

template <typename, typename = void >
struct has_foo_function_member_or_static : false_type {};

template <typename T>
struct has_foo_function_member_or_static<T, void_t<decltype(&T::Foo)>> : true_type {};

template <typename T>
using has_foo_function_member = 
	std::conditional_t<
		has_foo_function_member_or_static<T>::value,
		std::is_member_function_pointer<decltype(&T::Foo)>,
		false_type>;

int main()
{
    static_assert(has_foo_function_member<HasFoo>::value, "");
    //static_assert(has_foo_function_member<StaticFoo>::value, "");         // compile time err
    //static_assert(has_foo_function_member<NoFoo>::value, "");             // compile time err

    static_assert(has_foo_function_member_or_static<HasFoo>::value, "");    // compile time err
    static_assert(has_foo_function_member_or_static<StaticFoo>::value, ""); // compile time err
    //static_assert(has_foo_function_member_or_static<NoFoo>::value, "");   // compile time err
}

好了我们下次再见。🦀

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/14872.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

胜叔说SI_PI_EMC

第一课 分享的目的 书籍推荐 第二课 什么是理论分析 仿真不是目的&#xff0c;仿真是验证理论分析的方法 测试不是目的&#xff0c;测试是验证理论分析的方法 第三课 信号完整性简介 小型化、高功率、高密度 传输线理论&#xff1a;传输线是由 信号路径和返回路径共同组…

OSI七层模型、TCP/IP四层模型

OSI七层模型和TCP/IP四层模型 OSI七层模型 物理层&#xff1a;底层数据传输&#xff0c;如网线、网卡标准数据链路层&#xff1a;定义数据基本格式&#xff0c;如何传输如何标识&#xff1b;如网卡MAC地址网络层&#xff1a;定义IP地址&#xff0c;定义路由功能&#xff1b;如…

温度调制式差示扫描量热法(MTDSC)中的正弦波温度控制技术

摘要&#xff1a;在调制温度式差式扫描量热仪&#xff08;MTDSC&#xff09;中&#xff0c;关键技术之一是正弦波加热温度的实现&#xff0c;此技术是制约目前国内无法生产MTDSC量热仪的重要障碍&#xff0c;这主要是因为现有的PID温控技术根本无法实现不同幅值和频率正弦波这样…

中文版gpt-最新的人工智能gpt

最新的人工智能gpt 什么是GPT&#xff1f; GPT是一种自然语言处理和语言生成技术&#xff0c;它能够学习和理解自然语言&#xff0c;并生成高质量的文本。GPT是由OpenAI开发的&#xff0c;它采用了最新的深度学习技术&#xff0c;具备了强大的自我学习能力和语言理解能力。它…

【PaddleNLP-kie】关键信息抽取2:UIE模型做图片信息提取全流程

文章目录 本文参考UIE理论部分step0、UIEX原始模型使用网页体验本机安装使用环境安装使用docker的环境安装快速开始 step1、UIEX模型微调&#xff08;小样本学习&#xff09;数据标注&#xff08;label_studio&#xff09;导出数据转换微调训练&#xff1a;评估&#xff1a;定制…

第二节 ogre sdk 配置使用

上一节&#xff0c;我们介绍过了ogre源码的编译学习&#xff0c;在实际项目中&#xff0c;我们并不需要如此复杂的编译安装过程&#xff0c;可以直接使用官网提供的sdk库进行项目环境配置。下面简单介绍下配置过程。 一 OgreSDK下载 https://dl.cloudsmith.io/public/ogrecav…

Centos安全加固策略

目录 密码安全策略 设置密码的有效期和最小长度 设置用户密码的复杂度 登录安全策略 设置用户远程登录的安全策略 安全的远程管理方式 访问控制 限制root用户登录 修改ssh 22端口 设置登录超时时间 限制IP访问 安全审计 审核策略开启 日志属性设置 查看系统登录…

Google Play编写长描述的最佳实践

在我们为应用编写详细说明时&#xff0c;要遵循以下建议&#xff1a; 我们作为应用营销人员&#xff0c;要了解受众群体的需求和顾虑&#xff0c;如果不知道用户关心什么&#xff0c;那么我们可以查看关键词的搜索量、每个关键词的 Google Play 安装报告、当前关键字排名等等。…

element+vue小技巧和报错解决(持续更新)

目录 1-关于el-table复选框中表头和内容不对齐问题 2-日期选择器传值给后端格式不对 3-获取表格的当前行数据#default"{row}" 1-关于el-table复选框中表头和内容不对齐问题 <el-table:data"tableData"stripestyle"width: 100%"tooltip-ef…

Django框架之自定义管理页面

Django框架Admin站点管理一些默认的显示和功能包括语言都可以自定义设置处理&#xff0c;以贴近我们的实际业务。 属性说明 列表页属性 配置文件myapp/admin.py from django.contrib import admin from .models import Grades, Students# Register your models here.# 注册班…

算法训练 | Day41动态规划

343. 整数拆分 思路&#xff1a; 确定dp数组&#xff08;dp table&#xff09;以及下标的含义&#xff1a;dp[i]&#xff1a;分拆数字i&#xff0c;可以得到的最大乘积为dp[i]。 确定递推公式&#xff1a;dp[i] max(dp[i], max((i - j) * j, dp[i - j] * j)) 可以想 dp[i]最…

产品推荐丨智慧水利行业应用终端+云平台

智慧水利是我国智慧城市建设的重要延伸&#xff0c;是新时代水利现代化的战略目标&#xff0c;贯穿于防汛抗旱减灾、水资源合理配置和高效利用、水资源和河湖健康保障等体系。随着水利技术的集成发展与场景的成熟应用&#xff0c;我国水利现已完成从自动化阶段到信息化阶段的过…

会议论文与期刊论文的写作差异

AI领域的会议论文和期刊论文在撰写方法上存在一定的差异&#xff0c;读者需要理解这些差异&#xff0c;才能做到有的放矢&#xff0c;提高论文的命中率。如果按照会议论文的风格来写期刊论文&#xff0c;或者按照期刊论文的风格来写会议论文&#xff0c;论文命中的概率将大大降…

离散数学期末复习第一章 数理逻辑

离散数学 离散数学是研究各种各样的离散量的结构及离散量之间的关系一门学科&#xff0c;是计算机科学中基础理论的核心课程。 什么是连续变量&#xff1f; 在一定区间内可以任意取值的变量叫连续变量&#xff0c;其数值是连续不断的&#xff0c;相邻两个数值可作无限分割&a…

【社区图书馆】-《科技服务与价值链》总结

【为什么研究价值链】 价值链及价值链协同体系是现代产业集群的核心枢纽&#xff0c;是推进城市群及产业集群化、服务化、生态化发展的纽带。因而推进价值链协同&#xff0c;创新发展价值链协同业务科技资源体系&#xff0c;既是科技服务业创新的重要方向&#xff0c;也是重塑生…

第3章-运行时数据区

此章把运行时数据区里比较少的地方讲一下。虚拟机栈&#xff0c;堆&#xff0c;方法区这些地方后续再讲。 转载https://gitee.com/youthlql/JavaYouth/tree/main/docs/JVM。 运行时数据区概述及线程 前言 本节主要讲的是运行时数据区&#xff0c;也就是下图这部分&#xff0c…

ASO优化之如何回复Google Play评论

应用的平均评分会影响 Google Play 商店优化 和应用的 Google Play 排名。应用的评分越高&#xff0c;我们在搜索结果中的排名就越靠前。因此&#xff0c;当应用处于 4 星评级范围内时&#xff0c;它会被更多 Google Play 商店的访问者看到和发现。我们可以使用应用雷达中的评级…

听我一句劝,别去外包,干了三年,废了....

先说一下自己的情况&#xff0c;大专生&#xff0c;18年通过校招进入湖南某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试…

SAP ABAP MARA-MSBOOKPARTNO 制造商登记部分编号

BAPI_MATERIAL_SAVEDATA CLIENTDATA结构无此字段。 DATA:LS_TE_MARA TYPE BAPI_TE_MARA. DATA:LS_TE_MARAX TYPE BAPI_TE_MARAX. DATA:LT_BAPIPAREX TYPE TABLE OF BAPIPAREX. DATA:LS_BAPIPAREX TYPE BAPIPAREX. …

学生无线耳机哪款好?两百左右适合学生党的无线耳机推荐

学生无线耳机哪款好&#xff1f;现如今&#xff0c;学生党也成为了蓝牙耳机的主要用户群体之一。接下来&#xff0c;我来给学生群体推荐几款两百左右的无线耳机&#xff0c;一起来看看吧。 一、南卡小音舱Lite2蓝牙耳机 参考价&#xff1a;299 南卡小音舱的音质和佩戴体验都在…