如何使用升压preprocessor生成访问? [英] How to use boost preprocessor to generate accessors?

查看:115
本文介绍了如何使用升压preprocessor生成访问?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

例如

class A
{
    int m_x;
    float m_y;
    double m_z;

    int x() const {return m_x;}
    float y() const {return m_y;}
    double z() const {return m_z;}
};

变得像

class A
{
    MY_MACRO((int)(float)(double), (x)(y)(z));
};

请使用升压$ P $处理器序列,这样做,因为这个宏会与已经使用升压preprocesor序列其他现有的宏结合起来。

Please use boost prerocessor sequence to do it because this macro will combine with other existing macros which already use boost preprocesor sequence.

推荐答案

免责声明:您可能需要等待的情况下,一个更好的答案出现,即使你满意这个答案,因为我是从一个专家很远,这些可能不是是最好的方法。

Disclaimer:You should probably wait in case a better answer appears even if you are satisfied with this answer, because I'm far from an expert and these may not be the best approaches.

第一个方法:

//two different sequences
struct A
{
    MY_MACRO1((int)(float)(double),(x)(y)(z))
};

我觉得这种做法给人的那么可怕的前瞻性宏:

I think this approach gives the less scary-looking macro:

#define DECLARE_DATA_MEMBER1(R,TYPES,INDEX,NAME) \
BOOST_PP_SEQ_ELEM(INDEX,TYPES) BOOST_PP_CAT(m_,NAME);

#define DEFINE_ACCESSOR1(R,TYPES,INDEX,NAME) \
BOOST_PP_SEQ_ELEM(INDEX,TYPES) NAME(){ return BOOST_PP_CAT(m_,NAME); }

#define MY_MACRO1(TYPES,NAMES) \
BOOST_PP_SEQ_FOR_EACH_I(DECLARE_DATA_MEMBER1,TYPES,NAMES) \
public: \
BOOST_PP_SEQ_FOR_EACH_I(DEFINE_ACCESSOR1,TYPES,NAMES)

MY_MACRO 获得两个序列:类型姓名 。为了声明我用的是 BOOST_PP_SEQ_FOR_EACH_I 的序列姓名使用宏数据成员DECLARE_DATA_MEMBER1 和具有序列类型数据。这种调用 DECLARE_DATA_MEMBER1 4个参数:研究这是未使用的(我不知道它做什么) 类型(类型的顺序),首页(讲述了其中的迭代,我们现在是正确的,从0开始)和名称(原姓名与此对应的迭代序列的元素)。结果
DECLARE_DATA_MEMBER1 DEFINE_ACCESSOR1 的尸体很简单,我们只获得首页日在类型序列元素,并连接米_ 名称

MY_MACRO gets two sequences: TYPES and NAMES. In order to declare the data members I use a BOOST_PP_SEQ_FOR_EACH_I on the sequence NAMES using the macro DECLARE_DATA_MEMBER1 and having the sequence TYPES as data. This "invokes" DECLARE_DATA_MEMBER1 with 4 parameters: R which is unused (and I have no idea what it does), TYPES (the sequence of types), INDEX (tells in which iteration we are right now, starting at 0), and NAME (the element of the original NAMES sequence that corresponds with this iteration).
The "bodies" of DECLARE_DATA_MEMBER1 and DEFINE_ACCESSOR1 are simple, we simply get the INDEXth element in the types sequence, and concatenate m_ with NAME.

第二做法:

//just one sequence but you need to put two sets of parentheses around each pair
struct B
{
    MY_MACRO2(((int, x))((float,y))((double,z)))
};

这一次仍然是相当简单的,但必须使用双括号的不便。

This one is still fairly simple, but has the inconvenient of having to use double parentheses.

#define DECLARE_DATA_MEMBER2(R,_,TYPE_AND_NAME) \
BOOST_PP_TUPLE_ELEM(2,0,TYPE_AND_NAME) BOOST_PP_CAT(m_,BOOST_PP_TUPLE_ELEM(2,1,TYPE_AND_NAME));

#define DEFINE_ACCESSOR2(R,_,TYPE_AND_NAME) \
BOOST_PP_TUPLE_ELEM(2,0,TYPE_AND_NAME) BOOST_PP_TUPLE_ELEM(2,1,TYPE_AND_NAME)(){ return BOOST_PP_CAT(m_,BOOST_PP_TUPLE_ELEM(2,1,TYPE_AND_NAME)); }

#define MY_MACRO2(TYPES_AND_NAMES) \
BOOST_PP_SEQ_FOR_EACH(DECLARE_DATA_MEMBER2,_,TYPES_AND_NAMES) \
public: \
BOOST_PP_SEQ_FOR_EACH(DEFINE_ACCESSOR2,_,TYPES_AND_NAMES)

这时候,只有一个序列,所以我们并不需要在辅助宏的指数。为此 BOOST_PP_SEQ_FOR_EACH 用在使用宏 DECLARE_DATA_MEMBER2 TYPES_AND_NAMES和不传递任何额外数据。这个宏接受三个论据:研究再次使用的, _ (或 DATA ,也不用在这里),而 TYPE_AND_NAME (一元组的形式(类型,名称) )。结果
在两个辅助宏的尸体 BOOST_PP_TUPLE_ELEM 用于获取要么型(指数= 0)或名称(以指数= 1)。这个宏需要传递的元组的大小,你想要的元素和元组的索引。

This time there is only one sequence so we won't need the index in the helper macros. For this reason BOOST_PP_SEQ_FOR_EACH is used on TYPES_AND_NAMES using the macro DECLARE_DATA_MEMBER2 and without passing any extra data. This macro receives three "arguments": R again unused, _ (or DATA, also unused here), and TYPE_AND_NAME (a tuple in the form (TYPE,NAME)).
In the "bodies" of the two helper macros BOOST_PP_TUPLE_ELEM is used to get either the type(with index=0) or the name(with index=1). This macro needs to be passed the size of the tuple, the index of the element you want and the tuple.

第三个方法:

//one sequence but the macro is more complex
struct C
{
    MY_MACRO3((int,x)(float,y)(double,z))
};

这个宏从 BOOST_FUSION_ADAPT_STRUCT 和宏类似很大程度上借鉴。

This macro borrows heavily from BOOST_FUSION_ADAPT_STRUCT and similar macros.

//Heavily "inspired" from BOOST_FUSION_ADAPT_STRUCT
#define CREATE_MY_MACRO_PLACEHOLDER_FILLER_0(X, Y)  \
    ((X, Y)) CREATE_MY_MACRO_PLACEHOLDER_FILLER_1
#define CREATE_MY_MACRO_PLACEHOLDER_FILLER_1(X, Y)  \
    ((X, Y)) CREATE_MY_MACRO_PLACEHOLDER_FILLER_0
#define CREATE_MY_MACRO_PLACEHOLDER_FILLER_0_END
#define CREATE_MY_MACRO_PLACEHOLDER_FILLER_1_END

#define DECLARE_DATA_MEMBER3(R,_,TYPE_AND_NAME) \
BOOST_PP_TUPLE_ELEM(2,0,TYPE_AND_NAME) BOOST_PP_CAT(m_,BOOST_PP_TUPLE_ELEM(2,1,TYPE_AND_NAME));

#define DEFINE_ACCESSOR3(R,_,TYPE_AND_NAME) \
BOOST_PP_TUPLE_ELEM(2,0,TYPE_AND_NAME) BOOST_PP_TUPLE_ELEM(2,1,TYPE_AND_NAME)(){ return BOOST_PP_CAT(m_,BOOST_PP_TUPLE_ELEM(2,1,TYPE_AND_NAME)); }

#define MY_MACRO3(TYPES_AND_NAMES) \
BOOST_PP_SEQ_FOR_EACH(DECLARE_DATA_MEMBER3,_,BOOST_PP_CAT(CREATE_MY_MACRO_PLACEHOLDER_FILLER_0 TYPES_AND_NAMES,_END)) \
public: \
BOOST_PP_SEQ_FOR_EACH(DEFINE_ACCESSOR3,_,BOOST_PP_CAT(CREATE_MY_MACRO_PLACEHOLDER_FILLER_0 TYPES_AND_NAMES,_END))

在这种方法中,辅助宏是基本不变的。唯一的(大)的区别是,在的for_each使用的顺序不只是 TYPES_AND_NAMES ,但 BOOST_PP_CAT(CREATE_MY_MACRO_PLACEHOLDER_FILLER_0 TYPES_AND_NAMES,_END)。这是一个聪明的把戏,迫使双括号。它的工作原理是这样的:

In this approach the helper macros are basically unchanged. The only (big) difference is that the sequence used in the for_each is not simply TYPES_AND_NAMES but BOOST_PP_CAT(CREATE_MY_MACRO_PLACEHOLDER_FILLER_0 TYPES_AND_NAMES,_END). This is a clever trick to force the double parentheses. It works like this:

CREATE_MY_MACRO_PLACEHOLDER_FILLER_0(int,x)(float,y)_END
    //CREATE_MY_MACRO_PLACEHOLDER_FILLER_0(A,B)->((A,B))CREATE_MY_MACRO_PLACEHOLDER_FILLER_1
((int,x))CREATE_MY_MACRO_PLACEHOLDER_FILLER_1(float,y)_END
    //CREATE_MY_MACRO_PLACEHOLDER_FILLER_1(A,B)->((A,B))CREATE_MY_MACRO_PLACEHOLDER_FILLER_0
((int,x))((float,y))CREATE_MY_MACRO_PLACEHOLDER_FILLER_0_END
    //CREATE_MY_MACRO_PLACEHOLDER_FILLER_0_END->
((int,x))((float,y))


运行在Coliru。

这篇关于如何使用升压preprocessor生成访问?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆