参考nlohmann json设计Cereal宏 一行声明序列化函数
根据 nlohmann/json 宏实现,我设计了一个适用于 Cereal 序列化库的 CEREAL_SERIALIZE_INTRUSIVE/CEREAL_SERIALIZE_NON_INTRUSIVE
宏,它支持有限参数并自动生成序列化函数。
使用示例:
struct Product {int id;double price;std::string category;
};// 一行声明序列化函数
CEREAL_SERIALIZE_NON_INTRUSIVE(Product, id, price, category)// 等效于手动实现:
/*
template <class Archive>
void serialize(Archive& ar, const Product& t) {ar(::cereal::make_nvp("id", t.id),::cereal::make_nvp("price", t.price),::cereal::make_nvp("category", t.category));
}
*/// 嵌套结构体支持
struct OrderItem {int product_id;int quantity;
};struct Order {int order_id;std::vector<OrderItem> items;
};// 多行声明(自动展开)
CEREAL_SERIALIZE_NON_INTRUSIVE(OrderItem, product_id, quantity)
CEREAL_SERIALIZE_NON_INTRUSIVE(Order, order_id, items)// 生成的序列化代码:
/*
template <class Archive>
void serialize(Archive& ar, Order& order) {ar(::cereal::make_nvp("order_id", order.order_id),::cereal::make_nvp("items", order.items) // 自动调用OrderItem的序列化);
}
*///侵入的
struct MyRecord
{uint8_t x, y;float z;CEREAL_SERIALIZE_INTRUSIVE(x, y, z)
};
宏实现
#include <cereal/cereal.hpp>// 基础宏定义
#define CEREAL_EXPAND( x ) x
#define CEREAL_GET_MACRO(_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, NAME,...) NAME// 参数拼接宏(支持1-64个参数)
#define CEREAL_PASTE(...) CEREAL_EXPAND(CEREAL_GET_MACRO(__VA_ARGS__, \CEREAL_PASTE64, CEREAL_PASTE63, CEREAL_PASTE62, CEREAL_PASTE61, \CEREAL_PASTE60, CEREAL_PASTE59, CEREAL_PASTE58, CEREAL_PASTE57, \CEREAL_PASTE56, CEREAL_PASTE55, CEREAL_PASTE54, CEREAL_PASTE53, \CEREAL_PASTE52, CEREAL_PASTE51, CEREAL_PASTE50, CEREAL_PASTE49, \CEREAL_PASTE48, CEREAL_PASTE47, CEREAL_PASTE46, CEREAL_PASTE45, \CEREAL_PASTE44, CEREAL_PASTE43, CEREAL_PASTE42, CEREAL_PASTE41, \CEREAL_PASTE40, CEREAL_PASTE39, CEREAL_PASTE38, CEREAL_PASTE37, \CEREAL_PASTE36, CEREAL_PASTE35, CEREAL_PASTE34, CEREAL_PASTE33, \CEREAL_PASTE32, CEREAL_PASTE31, CEREAL_PASTE30, CEREAL_PASTE29, \CEREAL_PASTE28, CEREAL_PASTE27, CEREAL_PASTE26, CEREAL_PASTE25, \CEREAL_PASTE24, CEREAL_PASTE23, CEREAL_PASTE22, CEREAL_PASTE21, \CEREAL_PASTE20, CEREAL_PASTE19, CEREAL_PASTE18, CEREAL_PASTE17, \CEREAL_PASTE16, CEREAL_PASTE15, CEREAL_PASTE14, CEREAL_PASTE13, \CEREAL_PASTE12, CEREAL_PASTE11, CEREAL_PASTE10, CEREAL_PASTE9, \CEREAL_PASTE8, CEREAL_PASTE7, CEREAL_PASTE6, CEREAL_PASTE5, \CEREAL_PASTE4, CEREAL_PASTE3, CEREAL_PASTE2, CEREAL_PASTE1)(__VA_ARGS__))// 定义PASTE宏(1-64个参数)
#define CEREAL_PASTE2(func, v1) func(v1)
#define CEREAL_PASTE3(func, v1, v2) CEREAL_PASTE2(func, v1), CEREAL_PASTE2(func, v2)
#define CEREAL_PASTE4(func, v1, v2, v3) CEREAL_PASTE2(func, v1), CEREAL_PASTE3(func, v2, v3)
#define CEREAL_PASTE5(func, v1, v2, v3, v4) CEREAL_PASTE2(func, v1), CEREAL_PASTE4(func, v2, v3, v4)
#define CEREAL_PASTE6(func, v1, v2, v3, v4, v5) CEREAL_PASTE2(func, v1), CEREAL_PASTE5(func, v2, v3, v4, v5)
#define CEREAL_PASTE7(func, v1, v2, v3, v4, v5, v6) CEREAL_PASTE2(func, v1), CEREAL_PASTE6(func, v2, v3, v4, v5, v6)
#define CEREAL_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) CEREAL_PASTE2(func, v1), CEREAL_PASTE7(func, v2, v3, v4, v5, v6, v7)
#define CEREAL_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) CEREAL_PASTE2(func, v1), CEREAL_PASTE8(func, v2, v3, v4, v5, v6, v7, v8)
#define CEREAL_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) CEREAL_PASTE2(func, v1), CEREAL_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9)
#define CEREAL_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) CEREAL_PASTE2(func, v1), CEREAL_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10)
#define CEREAL_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) CEREAL_PASTE2(func, v1), CEREAL_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11)
#define CEREAL_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) CEREAL_PASTE2(func, v1), CEREAL_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12)
#define CEREAL_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) CEREAL_PASTE2(func, v1), CEREAL_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13)
#define CEREAL_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) CEREAL_PASTE2(func, v1), CEREAL_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14)
#define CEREAL_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) CEREAL_PASTE2(func, v1), CEREAL_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15)
#define CEREAL_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) CEREAL_PASTE2(func, v1), CEREAL_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16)
#define CEREAL_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) CEREAL_PASTE2(func, v1), CEREAL_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17)
#define CEREAL_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) CEREAL_PASTE2(func, v1), CEREAL_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18)
#define CEREAL_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) CEREAL_PASTE2(func, v1), CEREAL_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19)
#define CEREAL_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) CEREAL_PASTE2(func, v1), CEREAL_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20)
#define CEREAL_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) CEREAL_PASTE2(func, v1), CEREAL_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21)
#define CEREAL_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) CEREAL_PASTE2(func, v1), CEREAL_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22)
#define CEREAL_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) CEREAL_PASTE2(func, v1), CEREAL_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23)
#define CEREAL_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) CEREAL_PASTE2(func, v1), CEREAL_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24)
#define CEREAL_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) CEREAL_PASTE2(func, v1), CEREAL_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25)
#define CEREAL_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) CEREAL_PASTE2(func, v1), CEREAL_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26)
#define CEREAL_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) CEREAL_PASTE2(func, v1), CEREAL_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27)
#define CEREAL_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) CEREAL_PASTE2(func, v1), CEREAL_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28)
#define CEREAL_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) CEREAL_PASTE2(func, v1), CEREAL_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29)
#define CEREAL_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) CEREAL_PASTE2(func, v1), CEREAL_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30)
#define CEREAL_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) CEREAL_PASTE2(func, v1), CEREAL_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31)
#define CEREAL_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) CEREAL_PASTE2(func, v1), CEREAL_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32)
#define CEREAL_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) CEREAL_PASTE2(func, v1), CEREAL_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33)
#define CEREAL_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) CEREAL_PASTE2(func, v1), CEREAL_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34)
#define CEREAL_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) CEREAL_PASTE2(func, v1), CEREAL_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35)
#define CEREAL_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) CEREAL_PASTE2(func, v1), CEREAL_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36)
#define CEREAL_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) CEREAL_PASTE2(func, v1), CEREAL_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37)
#define CEREAL_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) CEREAL_PASTE2(func, v1), CEREAL_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38)
#define CEREAL_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) CEREAL_PASTE2(func, v1), CEREAL_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39)
#define CEREAL_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) CEREAL_PASTE2(func, v1), CEREAL_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40)
#define CEREAL_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) CEREAL_PASTE2(func, v1), CEREAL_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41)
#define CEREAL_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) CEREAL_PASTE2(func, v1), CEREAL_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42)
#define CEREAL_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) CEREAL_PASTE2(func, v1), CEREAL_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43)
#define CEREAL_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) CEREAL_PASTE2(func, v1), CEREAL_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44)
#define CEREAL_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) CEREAL_PASTE2(func, v1), CEREAL_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45)
#define CEREAL_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) CEREAL_PASTE2(func, v1), CEREAL_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46)
#define CEREAL_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) CEREAL_PASTE2(func, v1), CEREAL_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47)
#define CEREAL_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) CEREAL_PASTE2(func, v1), CEREAL_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48)
#define CEREAL_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) CEREAL_PASTE2(func, v1), CEREAL_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49)
#define CEREAL_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) CEREAL_PASTE2(func, v1), CEREAL_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50)
#define CEREAL_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) CEREAL_PASTE2(func, v1), CEREAL_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51)
#define CEREAL_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) CEREAL_PASTE2(func, v1), CEREAL_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52)
#define CEREAL_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) CEREAL_PASTE2(func, v1), CEREAL_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53)
#define CEREAL_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) CEREAL_PASTE2(func, v1), CEREAL_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54)
#define CEREAL_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) CEREAL_PASTE2(func, v1), CEREAL_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55)
#define CEREAL_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) CEREAL_PASTE2(func, v1), CEREAL_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56)
#define CEREAL_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) CEREAL_PASTE2(func, v1), CEREAL_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57)
#define CEREAL_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) CEREAL_PASTE2(func, v1), CEREAL_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58)
#define CEREAL_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) CEREAL_PASTE2(func, v1), CEREAL_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59)
#define CEREAL_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) CEREAL_PASTE2(func, v1), CEREAL_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60)
#define CEREAL_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) CEREAL_PASTE2(func, v1), CEREAL_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61)
#define CEREAL_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) CEREAL_PASTE2(func, v1), CEREAL_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62)
#define CEREAL_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) CEREAL_PASTE2(func, v1), CEREAL_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63)// 成员处理宏
#define CEREAL_MEMBER_NVP_NON_INTRUSIVE(member) ::cereal::make_nvp(#member, t.member)// 主序列化宏:非侵入的
#define CEREAL_SERIALIZE_NON_INTRUSIVE(...) \
template <class Archive> \
void serialize(Archive& ar, const Type& t) { \ar( CEREAL_PASTE(CEREAL_MEMBER_NVP_NON_INTRUSIVE, __VA_ARGS__) ); \
}// 主序列化宏:侵入的
#define CEREAL_SERIALIZE_INTRUSIVE(Type, ...) \
template <class Archive> \
void serialize(Archive& ar) { \ar( CEREAL_PASTE(CEREAL_NVP, __VA_ARGS__) ); \
}
技术解析:
- 参数计数与分派:
CEREAL_GET_MACRO
根据参数数量选择正确的PASTE宏- 支持最多64个成员变量(可根据需要扩展)
- 自动检测参数数量,无需手动指定
- 递归展开:
- 使用预处理器递归将参数展开为逗号分隔列表
CEREAL_PASTEn
宏将n个参数展开为n个CEREAL_MEMBER_NVP_NON_INTRUSIVE
调用- 保持代码生成的一致性
- 类型安全:
- 生成的序列化代码与手动实现完全相同
- 保留成员名称的字面量(通过
#member
字符串化) - 兼容Cereal的所有归档类型(XML/JSON/Binary等)
注意事项:
-
命名空间要求:
- 必须在结构体定义的相同命名空间内使用宏
- 符合Cereal的ADL查找规则
-
特殊类型处理:
- 指针类型需使用
CEREAL_NVP
包装 - 自定义类型需提前定义序列化函数
CEREAL_SERIALIZE_NON_INTRUSIVE(MyType, member1, member2) // 必须先定义 CEREAL_SERIALIZE_NON_INTRUSIVE(Container, myTypeInstance) // 后使用
- 指针类型需使用
-
版本控制:
template <class Archive> void serialize(Archive& ar, MyType& t, std::uint32_t version) {// 版本敏感处理 }
手动实现版本控制时,避免使用宏
此宏实现显著简化了Cereal的序列化代码,同时保持生成的代码质量和类型安全性,特别适合包含大量成员的结构体序列化场景。
在Cereal序列化库的宏系统中,#define CEREAL_EXPAND(x) x
和 CEREAL_GET_MACRO
等宏共同实现了一种可变参数宏的递归展开机制,用于生成序列化代码。
🧩 1. CEREAL_EXPAND(x) x
的作用
-
强制展开宏参数
此宏看似冗余(直接返回参数
x
),但在预处理阶段有特殊意义:-
当宏参数是另一个宏调用时(如
__VA_ARGS__
中包含嵌套宏),CEREAL_EXPAND
会强制预处理器对其参数进行二次展开。 -
例如:
#define FOO() 123 #define BAR(x) x BAR(FOO()) // 展开为 FOO(),而非 123 CEREAL_EXPAND(BAR(FOO())) // 展开为 123
-
在复杂宏嵌套场景中,它能解决宏展开顺序导致的“未展开参数”问题
-
⚙️ 2. CEREAL_GET_MACRO
的分派机制
此宏通过前置的 __VA_ARGS__
占位符动态选择实际调用的宏版本(如 CEREAL_PASTE64
、CEREAL_PASTE3
等):
#define CEREAL_GET_MACRO(_1,_2,_3,...,_64,NAME,...) NAME
-
参数计数与分派
-
宏利用
__VA_ARGS__
的可变参数特性,结合前置的占位参数(_1, _2, ..., _64
)统计参数数量。 -
例如调用
CEREAL_PASTE(CEREAL_NVP, __VA_ARGS__)
:__VA_ARGS__
对应CEREAL_NVP,a, b
(3个参数);CEREAL_GET_MACRO
匹配到_3
位置,返回NAME = CEREAL_PASTE3
;- 最终展开为
CEREAL_PASTE3(func, a, b)
。
-
调用
CEREAL_PASTE(CEREAL_MEMBER_NVP_NON_INTRUSIVE, id, name)
时:__VA_ARGS__
包含 3 个参数:CEREAL_MEMBER_NVP_NON_INTRUSIVE
、id
、name
。CEREAL_GET_MACRO
匹配参数列表_1=CEREAL_MEMBER_NVP_NON_INTRUSIVE
,_2=id
,_3=name
,并CEREAL_PASTEn
向后移动,定位到NAME = CEREAL_PASTE3
(因_3
对应第 3 个位置)
-
🔁 3. CEREAL_PASTEn
的递归展开
CEREAL_PASTEn
宏(如 CEREAL_PASTE3
)负责将参数列表展开为逗号分隔的表达式:
#define CEREAL_PASTE2(func, a) func(a)
#define CEREAL_PASTE3(func, a, b) func(a), func(b) // 展开多个参数
-
逐层拆解参数
以
CEREAL_PASTE4
为例:#define CEREAL_PASTE2(func, v1) func(v1) #define CEREAL_PASTE3(func, v1, v2) CEREAL_PASTE2(func, v1), CEREAL_PASTE2(func, v2) #define CEREAL_PASTE4(func, v1, v2, v3) CEREAL_PASTE2(func, v1), CEREAL_PASTE3(func, v2, v3)CEREAL_PASTE(CEREAL_NVP, x, y, z) // 展开为: CEREAL_NVP(x), CEREAL_NVP(y), CEREAL_NVP(z)
通过递归调用
CEREAL_PASTE2
、EREAL_PASTE3
等子宏,逐个处理参数。
🧠 4. 完整工作流程示例
假设用户调用:
CEREAL_MEMBER_NVP_NON_INTRUSIVE(MyStruct, id, name)
宏展开步骤:
-
参数分派:
CEREAL_PASTE(CEREAL_MEMBER_NVP_NON_INTRUSIVE, id, name)
→ 统计参数数量为3 → 调用CEREAL_PASTE3
。 -
成员处理:
CEREAL_PASTE3(CEREAL_MEMBER_NVP, id, name)
→
CEREAL_PASTE2(CEREAL_MEMBER_NVP_NON_INTRUSIVE, id), CEREAL_PASTE2(CEREAL_MEMBER_NVP_NON_INTRUSIVE, name)
→ 展开为
CEREAL_MEMBER_NVP(id), CEREAL_MEMBER_NVP(name)
。 -
生成序列化代码:
template <class Archive> void serialize(Archive& ar, MyStruct& t) {ar( cereal::make_nvp("id", t.id), cereal::make_nvp("name", t.name) ); }
⚠️ 5. 注意事项
- 参数数量限制
宏系统通常支持固定数量的参数版本(如64个),超限会导致编译失败。若需更多参数,需扩展CEREAL_PASTEn
宏。 - 调试复杂性
宏展开在预处理阶段完成,调试需通过gcc -E
查看预处理后的代码。 - 类型安全缺失
宏仅是文本替换,不检查成员类型(如t.name
需为可序列化类型)。
💎 总结
CEREAL_EXPAND
:解决宏嵌套展开问题,确保参数完全展开。CEREAL_GET_MACRO
:动态分派,根据参数数量选择展开逻辑。CEREAL_PASTEn
:递归展开参数,生成逗号分隔的表达式序列。
这一机制是C/C++预处理器的经典应用,通过宏组合显著简化了Cereal库的序列化声明,但需注意其调试和类型安全局限性。