1、关于序列化
百度词条:序列化(Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。
2、一些开源序列化工具
(1)Boost?的?serialization库
(2)谷歌的protobuf,官网地址:https://developers.google.cn/protocol-buffers/
(3)用于在C++结构体和json/xml之间互相转换的 XPACK? ? ? ? ?????????????? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??????????????????github地址:https://github.com/xyz347/xpack
3、使用QVariant实现序列化
(1)利用 QVariant 、QVariantMap、QJsonDocument?实现序列化
Serializable.h
#pragma once
#include <QVariant>
/*
*
* 可序列化基类,具体的类继承于它,可视为具有了可序列化的能力
*
*/
class Serializable
{
public:
virtual ~Serializable() {}
/*
* 转化为 QVariant 类型
*/
virtual QVariant toVariant() const = 0;
/*
* 从 QVariant 类型转为具体的数据
*/
virtual void fromVariant(const QVariant& variant) = 0;
};
Serializer.h
#pragma once
#include <QString>
#include "Serializable.h"
/*
*
* 抽象的序列化类,通过继承此类,可以拓展为 Json,xml,等格式
*
*/
class Serializer
{
public:
virtual ~Serializer() {}
/*
* 将可序列化的内容保存至文件中
*/
virtual void save(const Serializable& serializable, const QString& filepath, const QString& rootName = "") = 0;
/*
* 从文件中加载可序列化的内容
*/
virtual void load(Serializable& serializable, const QString& filepath) = 0;
};
JsonSerializer.h
#pragma once
#include "Serializer.h"
class JsonSerializer : public Serializer
{
public:
JsonSerializer();
void save(const Serializable& serializable, const QString& filepath, const QString& rootName = "") override;
void load(Serializable& serializable, const QString& filepath) override;
};
JsonSerializer.cpp
#include "JsonSerializer.h"
#include <QJsonDocument>
#include <QFile>
JsonSerializer::JsonSerializer() :
Serializer()
{
}
void JsonSerializer::save(const Serializable& serializable, const QString& filepath, const QString& /*rootName*/)
{
QJsonDocument doc = QJsonDocument::fromVariant(serializable.toVariant());
QFile file(filepath);
file.open(QFile::WriteOnly);
file.write(doc.toJson());
file.close();
}
void JsonSerializer::load(Serializable& serializable, const QString& filepath)
{
QFile file(filepath);
file.open(QFile::ReadOnly);
QJsonDocument doc = QJsonDocument::fromJson(file.readAll());
file.close();
serializable.fromVariant(doc.toVariant());
}
(2)使用
#include <QtCore/QCoreApplication>
#include "Serializer.h"
#include "JsonSerializer.h"
struct MyData : public Serializable
{
QString name;
int age;
QVariant toVariant() const
{
QVariantMap map;
map.insert("name", name);
map.insert("age", age);
return map;
}
void fromVariant(const QVariant& variant)
{
QVariantMap map = variant.toMap();
name = map.value("name").toString();
age = map.value("age").toInt();
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MyData data;
data.age = 18;
data.name = QStringLiteral("张三");
//【1】
JsonSerializer serializer;
serializer.save(data, "file.dat");
//【2】
MyData data2;
serializer.load(data2, "file.dat");
return a.exec();
}
4、使用QDataStream实现序列化
(1)在Qt助手里面搜索 Serializing Qt Data Types 查看支持序列化的类型,QPixmap,QImage,QVector,QMap等类型都是支持序列化操作的
(2)自定义结构体序列化示例
#include <QtCore/QCoreApplication>
#include <QString>
#include <QDataStream>
#include <QVector>
#include <QMap>
#include <QVariant>
#include <QByteArray>
struct MyData
{
QString name;
int value;
/*
* out
*/
friend QDataStream& operator << (QDataStream& stream, const MyData& d)
{
stream << d.name << d.value;
return stream;
}
/*
* in
*/
friend QDataStream& operator >>(QDataStream& stream, MyData& d)
{
stream >> d.name >> d.value;
return stream;
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MyData data{ "example", 1};
QByteArray ba;
/*
* serialize
*/
QDataStream out(&ba, QIODevice::WriteOnly);
out << data;
/*
* deserialize
*/
QDataStream in(&ba, QIODevice::ReadOnly);
MyData data2;
while (!in.atEnd()) {
in >> data2;
}
return a.exec();
}
(3)如上代码所示,自定义结构体需要重载实现<<?和 >>?操作符,可放置在结构体外实现如下定义:
QDataStream &operator<<(QDataStream &, const QXxx &);
QDataStream &operator>>(QDataStream &, QXxx &);
如果要放在结构体内部实现重载,则需在函数前加上?friend?关键字。
(4)观察这2个重载操作符,行为几乎一致,但是上面的写法太过于繁琐,每次定义一个结构体就需要重新写一遍,参考XPACK里面对于宏定义的使用,可利用 __VA_ARGS__?定义下列宏来对结构体参数打包:
#pragma once
#define STREAM_O <<
#define STREAM_I >>
#define P_PACK_EXPAND(...) __VA_ARGS__
#define P_PACK_COUNT(LEVEL, _99,_98,_97,_96,_95,_94,_93,_92,_91,_90,_89,_88,_87,_86,_85,_84,_83,_82,_81,_80,_79,_78,_77,_76,_75,_74,_73,_72,_71,_70,_69,_68,_67,_66,_65,_64,_63,_62,_61,_60,_59,_58,_57,_56,_55,_54,_53,_52,_51,_50,_49,_48,_47,_46,_45,_44,_43,_42,_41,_40,_39,_38,_37,_36,_35,_34,_33,_32,_31,_30,_29,_28,_27,_26,_25,_24,_23,_22,_21,_20,_19,_18,_17,_16,_15,_14,_13,_12,_11,_10,_9,_8,_7,_6,_5,_4,_3,_2,_1,N,...) LEVEL##N
#define P_PACK_N(LEVEL,ACTION, ...) P_PACK_EXPAND(P_PACK_COUNT(LEVEL, __VA_ARGS__,_99,_98,_97,_96,_95,_94,_93,_92,_91,_90,_89,_88,_87,_86,_85,_84,_83,_82,_81,_80,_79,_78,_77,_76,_75,_74,_73,_72,_71,_70,_69,_68,_67,_66,_65,_64,_63,_62,_61,_60,_59,_58,_57,_56,_55,_54,_53,_52,_51,_50,_49,_48,_47,_46,_45,_44,_43,_42,_41,_40,_39,_38,_37,_36,_35,_34,_33,_32,_31,_30,_29,_28,_27,_26,_25,_24,_23,_22,_21,_20,_19,_18,_17,_16,_15,_14,_13,_12,_11,_10,_9,_8,_7,_6,_5,_4,_3,_2,_1))P_PACK_EXPAND((ACTION, __VA_ARGS__))
#define P_PACK(ACTION, ...) P_PACK_N(PSTREAM, ACTION, __VA_ARGS__)
#define PSTREAM_1(ACTION, A) ACTION d.##A;
#define PSTREAM_2(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_1(ACTION, __VA_ARGS__))
#define PSTREAM_3(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_2(ACTION, __VA_ARGS__))
#define PSTREAM_4(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_3(ACTION, __VA_ARGS__))
#define PSTREAM_5(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_4(ACTION, __VA_ARGS__))
#define PSTREAM_6(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_5(ACTION, __VA_ARGS__))
#define PSTREAM_7(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_6(ACTION, __VA_ARGS__))
#define PSTREAM_8(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_7(ACTION, __VA_ARGS__))
#define PSTREAM_9(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_8(ACTION, __VA_ARGS__))
#define PSTREAM_10(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_9(ACTION, __VA_ARGS__))
#define PSTREAM_11(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_10(ACTION, __VA_ARGS__))
#define PSTREAM_12(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_11(ACTION, __VA_ARGS__))
#define PSTREAM_13(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_12(ACTION, __VA_ARGS__))
#define PSTREAM_14(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_13(ACTION, __VA_ARGS__))
#define PSTREAM_15(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_14(ACTION, __VA_ARGS__))
#define PSTREAM_16(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_15(ACTION, __VA_ARGS__))
#define PSTREAM_17(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_16(ACTION, __VA_ARGS__))
#define PSTREAM_18(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_17(ACTION, __VA_ARGS__))
#define PSTREAM_19(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_18(ACTION, __VA_ARGS__))
#define PSTREAM_20(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_19(ACTION, __VA_ARGS__))
#define PSTREAM_21(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_20(ACTION, __VA_ARGS__))
#define PSTREAM_22(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_21(ACTION, __VA_ARGS__))
#define PSTREAM_23(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_22(ACTION, __VA_ARGS__))
#define PSTREAM_24(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_23(ACTION, __VA_ARGS__))
#define PSTREAM_25(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_24(ACTION, __VA_ARGS__))
#define PSTREAM_26(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_25(ACTION, __VA_ARGS__))
#define PSTREAM_27(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_26(ACTION, __VA_ARGS__))
#define PSTREAM_28(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_27(ACTION, __VA_ARGS__))
#define PSTREAM_29(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_28(ACTION, __VA_ARGS__))
#define PSTREAM_30(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_29(ACTION, __VA_ARGS__))
#define PSTREAM_31(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_30(ACTION, __VA_ARGS__))
#define PSTREAM_32(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_31(ACTION, __VA_ARGS__))
#define PSTREAM_33(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_32(ACTION, __VA_ARGS__))
#define PSTREAM_34(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_33(ACTION, __VA_ARGS__))
#define PSTREAM_35(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_34(ACTION, __VA_ARGS__))
#define PSTREAM_36(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_35(ACTION, __VA_ARGS__))
#define PSTREAM_37(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_36(ACTION, __VA_ARGS__))
#define PSTREAM_38(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_37(ACTION, __VA_ARGS__))
#define PSTREAM_39(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_38(ACTION, __VA_ARGS__))
#define PSTREAM_40(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_39(ACTION, __VA_ARGS__))
#define PSTREAM_41(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_40(ACTION, __VA_ARGS__))
#define PSTREAM_42(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_41(ACTION, __VA_ARGS__))
#define PSTREAM_43(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_42(ACTION, __VA_ARGS__))
#define PSTREAM_44(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_43(ACTION, __VA_ARGS__))
#define PSTREAM_45(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_44(ACTION, __VA_ARGS__))
#define PSTREAM_46(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_45(ACTION, __VA_ARGS__))
#define PSTREAM_47(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_46(ACTION, __VA_ARGS__))
#define PSTREAM_48(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_47(ACTION, __VA_ARGS__))
#define PSTREAM_49(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_48(ACTION, __VA_ARGS__))
#define PSTREAM_50(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_49(ACTION, __VA_ARGS__))
#define PSTREAM_51(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_50(ACTION, __VA_ARGS__))
#define PSTREAM_52(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_51(ACTION, __VA_ARGS__))
#define PSTREAM_53(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_52(ACTION, __VA_ARGS__))
#define PSTREAM_54(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_53(ACTION, __VA_ARGS__))
#define PSTREAM_55(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_54(ACTION, __VA_ARGS__))
#define PSTREAM_56(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_55(ACTION, __VA_ARGS__))
#define PSTREAM_57(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_56(ACTION, __VA_ARGS__))
#define PSTREAM_58(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_57(ACTION, __VA_ARGS__))
#define PSTREAM_59(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_58(ACTION, __VA_ARGS__))
#define PSTREAM_60(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_59(ACTION, __VA_ARGS__))
#define PSTREAM_61(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_60(ACTION, __VA_ARGS__))
#define PSTREAM_62(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_61(ACTION, __VA_ARGS__))
#define PSTREAM_63(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_62(ACTION, __VA_ARGS__))
#define PSTREAM_64(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_63(ACTION, __VA_ARGS__))
#define PSTREAM_65(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_64(ACTION, __VA_ARGS__))
#define PSTREAM_66(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_65(ACTION, __VA_ARGS__))
#define PSTREAM_67(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_66(ACTION, __VA_ARGS__))
#define PSTREAM_68(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_67(ACTION, __VA_ARGS__))
#define PSTREAM_69(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_68(ACTION, __VA_ARGS__))
#define PSTREAM_70(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_69(ACTION, __VA_ARGS__))
#define PSTREAM_71(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_70(ACTION, __VA_ARGS__))
#define PSTREAM_72(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_71(ACTION, __VA_ARGS__))
#define PSTREAM_73(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_72(ACTION, __VA_ARGS__))
#define PSTREAM_74(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_73(ACTION, __VA_ARGS__))
#define PSTREAM_75(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_74(ACTION, __VA_ARGS__))
#define PSTREAM_76(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_75(ACTION, __VA_ARGS__))
#define PSTREAM_77(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_76(ACTION, __VA_ARGS__))
#define PSTREAM_78(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_77(ACTION, __VA_ARGS__))
#define PSTREAM_79(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_78(ACTION, __VA_ARGS__))
#define PSTREAM_80(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_79(ACTION, __VA_ARGS__))
#define PSTREAM_81(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_80(ACTION, __VA_ARGS__))
#define PSTREAM_82(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_81(ACTION, __VA_ARGS__))
#define PSTREAM_83(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_82(ACTION, __VA_ARGS__))
#define PSTREAM_84(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_83(ACTION, __VA_ARGS__))
#define PSTREAM_85(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_84(ACTION, __VA_ARGS__))
#define PSTREAM_86(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_85(ACTION, __VA_ARGS__))
#define PSTREAM_87(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_86(ACTION, __VA_ARGS__))
#define PSTREAM_88(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_87(ACTION, __VA_ARGS__))
#define PSTREAM_89(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_88(ACTION, __VA_ARGS__))
#define PSTREAM_90(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_89(ACTION, __VA_ARGS__))
#define PSTREAM_91(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_90(ACTION, __VA_ARGS__))
#define PSTREAM_92(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_91(ACTION, __VA_ARGS__))
#define PSTREAM_93(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_92(ACTION, __VA_ARGS__))
#define PSTREAM_94(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_93(ACTION, __VA_ARGS__))
#define PSTREAM_95(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_94(ACTION, __VA_ARGS__))
#define PSTREAM_96(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_95(ACTION, __VA_ARGS__))
#define PSTREAM_97(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_96(ACTION, __VA_ARGS__))
#define PSTREAM_98(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_97(ACTION, __VA_ARGS__))
#define PSTREAM_99(ACTION, A, ...) ACTION d.##A P_PACK_EXPAND(PSTREAM_98(ACTION, __VA_ARGS__))
#define QPACK(T, ...)\
friend QDataStream& operator<< (QDataStream& stream, const T& d)\
{\
stream P_PACK_EXPAND(P_PACK(STREAM_O, __VA_ARGS__));\
return stream;\
}\
\
friend QDataStream& operator>> (QDataStream& stream, T& d)\
{\
stream P_PACK_EXPAND(P_PACK(STREAM_I, __VA_ARGS__));\
return stream;\
}
(5)接下来就可以使用定义好的 QPACK?宏来改造我们之前的结构体:
#include <QtCore/QCoreApplication>
#include <QString>
#include <QDataStream>
#include <QVector>
#include <QMap>
#include <QVariant>
#include <QByteArray>
struct MyData
{
QString name;
int value;
QPACK(MyData, name, value);
};
struct MyData2
{
QVector vec;
qint32 value;
qint32 value2;
QString name;
QPACK(MyData2, vec, value, value2, name);
};
struct MyData3
{
QMap<int, int> map;
QPACK(MyData3, map);
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MyData data{ "example", 1};
QByteArray ba;
/*
* serialize
*/
QDataStream out(&ba, QIODevice::WriteOnly);
out << data;
/*
* deserialize
*/
QDataStream in(&ba, QIODevice::ReadOnly);
MyData data2;
while (!in.atEnd()) {
in >> data2;
}
return a.exec();
}
(6)关于宏定义的说明
__VA_ARGS__ 作为参数传递给另一个宏时会被当成一个普通的参数,需要用一个宏展开来包裹一下 (即以上宏代码中的 P_PACK_EXPAND)
P_PACK_COUNT 和 P_PACK_N 搭配使用来确定元素个数,为便于理解其工作原理,可简化如下:
#include <iostream>
#define P_PACK_EXPAND(...) __VA_ARGS__
#define P_PACK_COUNT(_5,_4,_3,_2,_1,N,...) N
#define P_PACK_N(...) P_PACK_EXPAND(P_PACK_COUNT(__VA_ARGS__,_5,_4,_3,_2,_1))
int main()
{
/*
* P_PACK_N(1, 2, 3) 可看为
*
*
* P_PACK_COUNT(_5,_4,_3,_2,_1, N,...)
* |
* P_PACK_N( 1, 2, 3,_5,_4,_3,_2,_1)
*
*
*/
P_PACK_N(1, 2, 3); // _3
return 0;
}
源代码:https://download.csdn.net/download/pzywinner/20966625
|