【“宏孩儿”入门】通过宏定义将类型和函数结构解耦

想象这样一个场景,我们有一个表结构体StudentInfo,同时用数组存储它作为一张表,我们需要提供一套根据Key来增删改查的函数操作这张表。
(这里可能有聪明的小伙伴会想到为什么不用哈希表来存储,这样不就自带一套根据Key来增删改查函数了吗?
是的一般情况下可以这样,但也有些情景下不能使用哈希表,比如UE中TSet不支持同步。)
但如果每有一张这样的表我们都要写一套增删改查函数未免太累了。
我们仔细观察增删改查函数时会发现,除了操作的表,key不同外,代码结构上是相同的,那怎么让表和函数结构解耦呢?
因为表可能是私有成员同时还需要用到表的key,所以用模板还不太好解决。

可以考虑用宏来做。
比如在某个模块中有多张表:

struct StudentInfo{
	int Id;
	std::string Val1;
	float Val2;
};

struct Fish{
	//...
}
//...

class Module{
//...
private:
	//SaveGame
	std::vector<StudentInfo> StudentInfoTable;
	std::vector<FishInfo> FishInfoTable;
	//其他表...
public:
    //各表的增删改查函数...
}

比如我们想为所有表提供一个Has函数,可以写个宏:
(如果对##的作用不了解可以点击看这篇文章)

#define DECLARE_DATA_TABLE_HAS_METHOD(DataArray, KeyType, KeyField) \
bool DataArray##HasKey(KeyType FindBy##KeyField){ 					\
    bool IsHas = false; 											\
    for(const auto &Row : DataArray){ 								\
        if(Row.KeyField == FindBy##KeyField){ 						\
			IsHas = true; 											\
			break; 													\
		} 															\
    }																\
	return IsHas; 													\
} 																	\

(这里不讨论实现性能问题,那不是这篇文章的主题)
然后可以在需要定义has函数的模块中加上这个宏传入表和key信息就等于生成了一个该表的Has函数:

DECLARE_DATA_TABLE_CRUD_METHOD(StudentInfoTable, StudentInfo, int, Id)

等价于

bool StudentInfoTableHasKey(KeyType FindById){
	//...
}

接下来就可以举一反三写出生成其它函数的宏,同时我们还可以写个宏来专门负责打包这些宏:

//生成数据表基础的增删改查方法
#define DECLARE_DATA_TABLE_CRUD_METHOD(DataArray, RowType, KeyType, KeyField) \
DECLARE_DATA_TABLE_HAS_METHOD(DataArray, KeyType, KeyField)\
DECLARE_DATA_TABLE_FIND_METHOD(DataArray, RowType, KeyType, KeyField)\
DECLARE_DATA_TABLE_FIND_OR_ADD_METHOD(DataArray, RowType, KeyType, KeyField)\
//...

这样我们为每张表写增删改查函数就只需要一条宏:

DECLARE_DATA_TABLE_CRUD_METHOD(StudentInfoTable, StudentInfo, int, Id)

这个例子只是用来理解思路。
完整样例代码

#include<iostream>
#include<string>
#include<vector>

#define DECLARE_DATA_TABLE_HAS_METHOD(DataArray, KeyType, KeyField) \
bool DataArray##HasKey(KeyType FindBy##KeyField){ 					\
    bool IsHas = false; 											\
    for(const auto &Row : DataArray){ 								\
        if(Row.KeyField == FindBy##KeyField){ 						\
			IsHas = true; 											\
			break; 													\
		} 															\
    }																\
	return IsHas; 													\
} 																	\

#define DECLARE_DATA_TABLE_FIND_METHOD(DataArray, RowType, KeyType, KeyField)\
RowType *DataArray##FindRow(KeyType FindBy##KeyField){\
	RowType *Ret = nullptr;\
	for(auto &Row : DataArray){\
		if(Row.KeyField == FindBy##KeyField){\
			Ret = &Row;\
			break;\
		}\
	}\
	return Ret;\
}\

//前置依赖:Find
#define DECLARE_DATA_TABLE_FIND_OR_ADD_METHOD(DataArray, RowType, KeyType, KeyField)  \
RowType &DataArray##FindOrAddRow(KeyType In##KeyField){\
	RowType *FindRow = DataArray##FindRow(In##KeyField);\
	if(FindRow == nullptr){\
		RowType Row;\
		Row.KeyField = In##KeyField;\
		DataArray.push_back(Row);\
		FindRow = &DataArray[DataArray.size()-1];\
	}\
	return *FindRow;\
}\


//生成数据表基础的增删改查方法
#define DECLARE_DATA_TABLE_CRUD_METHOD(DataArray, RowType, KeyType, KeyField) \
DECLARE_DATA_TABLE_HAS_METHOD(DataArray, KeyType, KeyField)\
DECLARE_DATA_TABLE_FIND_METHOD(DataArray, RowType, KeyType, KeyField)\
DECLARE_DATA_TABLE_FIND_OR_ADD_METHOD(DataArray, RowType, KeyType, KeyField)\



struct StudentInfo{
	int Id;
	std::string Val1;
	float Val2;
};

class Module{
//...
private:
	//SaveGame
	std::vector<StudentInfo> StudentInfoTable;
public:
	
	DECLARE_DATA_TABLE_CRUD_METHOD(StudentInfoTable, StudentInfo, int, Id)
	/*
	DECLARE_DATA_TABLE_HAS_METHOD(StudentInfoTable, int, Id);
	DECLARE_DATA_TABLE_FIND_METHOD(StudentInfoTable, StudentInfo, int, Id);
	DECLARE_DATA_TABLE_FIND_OR_ADD_METHOD(StudentInfoTable, StudentInfo, int, Id);
	*/
};

int main(){
	Module NewModule;
	std::cout << NewModule.StudentInfoTableHasKey(5) << "\n";
	std::cout << NewModule.StudentInfoTableFindRow(5) << "\n";
	StudentInfo &FindStudentInfo = NewModule.StudentInfoTableFindOrAddRow(2001);
	FindStudentInfo.Val1 = "zsd";
	FindStudentInfo.Val2 = 1.5f;
	std::cout << NewModule.StudentInfoTableFindOrAddRow(2001).Val2 << "\n";
	
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值