欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

【原创】自己手写实现Boost序列化简易版

程序员文章站 2023-10-08 23:11:23
设计思路 在与多个系统进行网络交互时,序列化是不可缺少的技术。编写一个C++语言的序列化实现,是练习运用模板元编程的绝佳案例,理解C++模板是如何"面向编译期编程"的(业内好像没有这个说法)。序列化对象处理基础数据类型和类类型,boost的序列化功能划分得更细致,基本支持了C++语言的序列化,但是在 ......

设计思路

 

在与多个系统进行网络交互时,序列化是不可缺少的技术。编写一个c++语言的序列化实现,是练习运用模板元编程的绝佳案例,理解c++模板是如何"面向编译期编程"的(业内好像没有这个说法)。序列化对象处理基础数据类型和类类型,boost的序列化功能划分得更细致,基本支持了c++语言的序列化,但是在业务开发中,支持这两种已经足够用了。对于基础数据类型的序列化,需要合理组织序列化的协议格式;对于类类型的序列化,类是由基础数据类型组成的,最终转换为基础数据类型的序列化。

代码思路

 

序列化实现类class ctextserialize,反序列化实现类class ctextdeserialize;这两个类都通过业务类的模板函数serialize以传参的方式分别实现序列化和反序列化。class ctextserialize中的重载函数serialize分别实现基础数据类型和类类型的序列化;class ctextdeserialize中的重载函数deserialize分别实现基础数据类型和类类型的反序列化。这两个类在处理类类型序列化/反序列化时,都调用了class caccess的静态函数serialize。对于容器vector和map这种特殊的类类型,需要单独实现偏特化的class caccess。整体代码设计思路需要结合完整代码实现细节进行理解。

完整代码

 

代码基于c++98进行编写,采用gcc4.8.5编译器编译,测试运行在centos7.3环境。

在main函数中,代码分为四段:

第一段,采用输入输出流操作不同基础数据类型的变量;

第二段,使用模板判断变量类型是基础数据类型还是类类型;

第三段,对基础数据类型进行序列化和反序列化;

第四段,对类类型进行序列化和反序列化。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326

327

328

329

330

#include <iostream>

#include <sstream>

#include <map>

#include <vector>

#include <stdint.h>

using namespace std;

 

template<typename t>

struct is_class_imp{ //采用boosttype_traits的方式判断,判断一个类型是否是一个类类型

typedef char class_type; //一个字节

typedef int32_t non_class_type; //四个字节

template<typename c> static class_type is_class_check(void(c::*)(void)); //类类型匹配到的模板函数

template<typename c> static non_class_type is_class_check(...); //基础类型匹配到的模板函数

 

static const bool value = (sizeof(is_class_check<t>(0)) == sizeof(class_type)); //value的值在编译期决定

};

template<>

struct is_class_imp<string>{ //模板特化,string可以作为基础类型处理,其实是类类型

static const bool value = false;

};

template<typename t>

struct is_class : is_class_imp<t>{}; //继承

 

template<bool c_>

struct bool_plt{}; //用于编译期条件判断的模板,bool_plt<true>bool_plt<false>

 

template<typename c_, typename f1, typename f2> //c_编译期的条件,依据条件判断,动态定义类型f1f2

struct eval_if{};

template<typename f1, typename f2> //模板偏特化,typename c_

struct eval_if<bool_plt<true>, f1, f2>{ //c_编译期条件为bool_plt<true>时,定义类型f1

typedef f1 type;

};

template<typename f1, typename f2> //模板偏特化,typename c_

struct eval_if<bool_plt<false>, f1, f2>{ //c_编译期条件为bool_plt<false>时,定义类型f2

typedef f2 type;

};

 

template<typename archive, typename t>

class caccess //对类类型对象,应该序列化还是反序列化的控制函数

{

public:

static void serialize(archive& ar, t& t){ //调用类类型对象的serialize函数,序列化还是反序列化由ar参数决定

t.serialize(ar);

}

};

template<typename archive, typename t>

struct cfreemarshall{ //序列化结构体类型

static void invoke(archive& ar, const t& t){

caccess<archive, t>::marshall(ar, t);

}

};

template<typename archive, typename t>

struct cfreedemarshall{ //反序列化结构体类型

static void invoke(archive& ar, t& t){

caccess<archive, t>::demarshall(ar, t);

}

};

template<typename archive, typename t>

struct cfreeinvoke{ //序列化和反序列化统一调用模版函数,在编译期决定调用其一

static void invoke(archive& ar, t& t){

typedef typename eval_if<typename archive::is_marshall, //假如ar对象是序列化对象

cfreemarshall<archive, t>, //定义序列化类型

cfreedemarshall<archive, t> >::type typex; //否则定义反序列化类型

typex::invoke(ar, t); //调用序列化或反序列化函数,在编译期动态判断决定

}

};

 

template<typename archive, typename t>

class caccess<archive, vector<t> > //模板偏特化,实现vector容器的序列化和反序列化

{

public:

static void serialize(archive& ar, vector<t>& t) //调用序列化或反序列化函数,在编译期动态判断决定

{

cfreeinvoke<archive, vector<t> >::invoke(ar, t);

}

static void marshall(archive& ar, const vector<t>& t) //序列化

{

int len = t.size();

ar << len << " ";

for (int i = 0; i < len; i++)

{

ar << t[i] << " ";

}

}

static void demarshall(archive& ar, vector<t>& t) //反序列化

{

int len = 0;

ar >> len;

t.clear();

for (int i = 0; i < len; i++)

{

t tmp;

ar >> tmp;

t.

(0)
打赏 【原创】自己手写实现Boost序列化简易版 微信扫一扫

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

【原创】自己手写实现Boost序列化简易版
验证码: 【原创】自己手写实现Boost序列化简易版
Copyright © 2017-2022  保留所有权利. 粤ICP备17035492号-1
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com