最近准备重构一下我的kapok库,让mta函数可以返回元素为kv的tupl,例如:
structprson
{
std::stringnam;
intag;
META(nam,ag)//定义一个支持变参的mta函数
};
intmain()
{
prsonp={“tom”,20};
autotp=p.mta();
static_assrt(std::is_sam(std::tuplstd::pairstd::string,int,dcltyp(tp),“notsam”);
//tp在内存中是这样的{{“nam”:”tom”},{“ag”:20}};
rturn0;
}
类似这个META的实现我在msgpack的库里看到了,在这里:
仅仅是宏元的代码就数百行了,看起来非常复杂,msgpack之所以用这么复杂的方式去实现恐怕是为了支持c++98/0标准。本来想看看msgpack是如何实现META函数的,但是它的宏元代码读起来比较困难,于是作罢。
后来想起群里的ddrm实现了类似的功能,据说没有msgpack这么复杂,简洁一些,于是向ddrm要来了代码(在此感谢ddrm分享的源码)。他的代码也是用宏元,但是比msgpack的代码少很多,将近一百行代码。不过,我不太喜欢这么复杂的代码,我希望用一种更简单的方式去实现这个效果。这里附上ddrm的代码,大家可以借鉴参考一下。
#ifndfTUPLE_MACRO_DEF_H
#dfinTUPLE_MACRO_DEF_H
#dfinMARCO_EXPAND(arg_list)arg_list
#dfinAPPLY_VARIADIC_MACRO(macro,tupl)macrotupl
#dfinADD_REFERENCE(t)std::rfrnc_wrapprdcltyp(t)(t)
#dfinADD_REFERENCE_CONST(t)std::rfrnc_wrapprstd::add_const_tdcltyp(t)(t)
#dfinPAIR_OBJECT(t)std::mak_pair(#t,ADD_REFERENCE(t))
#dfinPAIR_OBJECT_CONST(t)std::mak_pair(#t,ADD_REFERENCE_CONST(t))
#dfinMAKE_TUPLE(...)autotupl(){rturnstd::mak_tupl(__VA_ARGS__);}
#dfinMAKE_TUPLE_CONST(...)autotupl()const{rturnstd::mak_tupl(__VA_ARGS__);}
/*arglistxpandmacro,nowsupport40args*/
#dfinMAKE_ARG_LIST_1(op,arg,...)op(arg)
#dfinMAKE_ARG_LIST_2(op,arg,...)op(arg),MARCO_EXPAND(MAKE_ARG_LIST_1(op,__VA_ARGS__))
#dfinMAKE_ARG_LIST_(op,arg,...)op(arg),MARCO_EXPAND(MAKE_ARG_LIST_2(op,__VA_ARGS__))
#dfinMAKE_ARG_LIST_4(op,arg,...)op(arg),MARCO_EXPAND(MAKE_ARG_LIST_(op,__VA_ARGS__))
#dfinMAKE_ARG_LIST_5(op,arg,...)op(arg),MARCO_EXPAND(MAKE_ARG_LIST_4(op,__VA_ARGS__))
#dfinMAKE_ARG_LIST_6(op,arg,...)op(arg),MARCO_EXPAND(MAKE_ARG_LIST_5(op,__VA_ARGS__))
#dfinMAKE_ARG_LIST_7(op,arg,...)op(arg),MARCO_EXPAND(MAKE_ARG_LIST_6(op,__VA_ARGS__))
#dfinMAKE_ARG_LIST_8(op,arg,...)op(arg),MARCO_EXPAND(MAKE_ARG_LIST_7(op,__VA_ARGS__))
#dfinMAKE_ARG_LIST_9(op,arg,...)op(arg),MARCO_EXPAND(MAKE_ARG_LIST_8(op,__VA_ARGS__))
#dfinMAKE_ARG_LIST_10(op,arg,...)op(arg),MARCO_EXPAND(MAKE_ARG_LIST_9(op,__VA_ARGS__))
#dfinMAKE_ARG_LIST_11(op,arg,...)op(arg),MARCO_EXPAND(MAKE_ARG_LIST_10(op,__VA_ARGS__))
#dfinMAKE_ARG_LIST_12(op,arg,...)op(arg),MARCO_EXPAND(MAKE_ARG_LIST_11(op,__VA_ARGS__))
#dfinMAKE_ARG_LIST_1(op,arg,...)op(arg),MARCO_EXPAND(MAKE_ARG_LIST_12(op,__VA_ARGS__))
#dfinMAKE_ARG_LIST_14(op,arg,...)op(arg),MARCO_EXPAND(MAKE_ARG_LIST_1(op,__VA_ARGS__))
#dfinMAKE_ARG_LIST_15(op,arg,...)op(arg),MARCO_EXPAND(MAKE_ARG_LIST_14(op,__VA_ARGS__))
#dfinMAKE_ARG_LIST_16(op,arg,...)op(arg),MARCO_EXPAND(MAKE_ARG_LIST_15(op,__VA_ARGS__))
#dfinMAKE_ARG_LIST_17(op,arg,...)op(arg),MARCO_EXPAND(MAKE_ARG_LIST_16(op,__VA_ARGS__))
#dfinMAKE_ARG_LIST_18(op,arg,...)op(arg),MARCO_EXPAND(MAKE_ARG_LIST_17(op,__VA_ARGS__))
#dfinMAKE_ARG_LIST_19(op,arg,...)op(arg),MARCO_EXPAND(MAKE_ARG_LIST_18(op,__VA_ARGS__))
#dfinMAKE_ARG_LIST_20(op,arg,...)op(arg),MARCO_EXPAND(MAKE_ARG_LIST_19(op,__VA_ARGS__))
#dfinMAKE_ARG_LIST_21(op,arg,...)op(arg),MARCO_EXPAND(MAKE_ARG_LIST_20(op,__VA_ARGS__))
#dfinMAKE_ARG_LIST_22(op,arg,...)op(arg),MARCO_EXPAND(MAKE_ARG_LIST_21(op,__VA_ARGS__))
#dfinMAKE_ARG_LIST_2(op,arg,...)op(arg),MARCO_EXPAND(MAKE_ARG_LIST_22(op,__VA_ARGS__))
#dfinMAKE_ARG_LIST_24(op,arg,...)op(arg),MARCO_EXPAND(MAKE_ARG_LIST_2(op,__VA_ARGS__))
#dfinMAKE_ARG_LIST_25(op,arg,...)op(arg),MARCO_EXPAND(MAKE_ARG_LIST_24(op,__VA_ARGS__))
#dfinMAKE_ARG_LIST_26(op,arg,...)op(arg),MARCO_EXPAND(MAKE_ARG_LIST_25(op,__VA_ARGS__))
#dfinMAKE_ARG_LIST_27(op,arg,...)op(arg),MARCO_EXPAND(MAKE_ARG_LIST_26(op,__VA_ARGS__))
#dfinMAKE_ARG_LIST_28(op,arg,...)op(arg),MARCO_EXPAND(MAKE_ARG_LIST_27(op,__VA_ARGS__))
#dfinMAKE_ARG_LIST_29(op,arg,...)op(arg),MARCO_EXPAND(MAKE_ARG_LIST_28(op,__VA_ARGS__))
#dfinMAKE_ARG_LIST_0(op,arg,...)op(arg),MARCO_EXPAND(MAKE_ARG_LIST_29(op,__VA_ARGS__))
#dfinMAKE_ARG_LIST_1(op,arg,...)op(arg),MARCO_EXPAND(MAKE_ARG_LIST_0(op,__VA_ARGS__))
#dfinMAKE_ARG_LIST_2(op,arg,...)op(arg),MARCO_EXPAND(MAKE_ARG_LIST_1(op,__VA_ARGS__))
#dfinMAKE_ARG_LIST_(op,arg,...)op(arg),MARCO_EXPAND(MAKE_ARG_LIST_2(op,__VA_ARGS__))
#dfinMAKE_ARG_LIST_4(op,arg,...)op(arg),MARCO_EXPAND(MAKE_ARG_LIST_(op,__VA_ARGS__))
#dfinMAKE_ARG_LIST_5(op,arg,...)op(arg),MARCO_EXPAND(MAKE_ARG_LIST_4(op,__VA_ARGS__))
#dfinMAKE_ARG_LIST_6(op,arg,...)op(arg),MARCO_EXPAND(MAKE_ARG_LIST_5(op,__VA_ARGS__))
#dfinMAKE_ARG_LIST_7(op,arg,...)op(arg),MARCO_EXPAND(MAKE_ARG_LIST_6(op,__VA_ARGS__))
#dfinMAKE_ARG_LIST_8(op,arg,...)op(arg),MARCO_EXPAND(MAKE_ARG_LIST_7(op,__VA_ARGS__))
#dfinMAKE_ARG_LIST_9(op,arg,...)op(arg),MARCO_EXPAND(MAKE_ARG_LIST_8(op,__VA_ARGS__))
#dfinMAKE_ARG_LIST_40(op,arg,...)op(arg),MARCO_EXPAND(MAKE_ARG_LIST_9(op,__VA_ARGS__))
/*mmbdmarco,usingEMMBED_TUPLE(5,a,b,c,d,)*/
//notusMACRO_CONCATlikA##_##Bdirctmaycausmarcoxpandrror
#dfinMACRO_CONCAT(A,B)MACRO_CONCAT1(A,B)
#dfinMACRO_CONCAT1(A,B)A##_##B
#dfinMAKE_ARG_LIST(N,op,arg,...)\
MACRO_CONCAT(MAKE_ARG_LIST,N)(op,arg,__VA_ARGS__)
#dfinEMMBED_TUPLE(N,...)\
MAKE_TUPLE(MAKE_ARG_LIST(N,PAIR_OBJECT,__VA_ARGS__))\
MAKE_TUPLE_CONST(MAKE_ARG_LIST(N,PAIR_OBJECT_CONST,__VA_ARGS__))