【问题标题】:Construct boost::fusion::map (and more) through custom macro通过自定义宏构造 boost::fusion::map (以及更多)
【发布时间】:2014-08-11 08:32:52
【问题描述】:

我有一个特征类,其中包含每个类在 boost::fusion::map 中的所有信号。

例子:

template <typename T> struct EventTraits;

class SomeClass;

template <> struct EventTraits<SomeClass>
{
    struct Started;
    struct Finished;
    typedef boost::fusion::map<
        boost::fusion::pair<Started, boost::signals2::signal<void()>>,
        boost::fusion::pair<Finished, boost::signals2::signal<void(int)>>
    > Events;
};

因为我经常需要这种特质特化,所以我想有一个宏来节省我的打字时间,就像这个虚构的例子:

CONSTRUCT_EVENTS(
    SomeClass,
    (Started, void())
    (Finished, void(int))
)

如何实现这样的CONSTRUCT_EVENTS 宏? 作为起点,我查看了BOOST_FUSION_ADAPT_STRUCT,然后查看了 Boost Preprocessor,但我还没有使用过后者,所以我希望有人可以指导我。

【问题讨论】:

  • 如果我正确理解您的问题,为什么这需要宏?你不能为此使用模板吗?无论何时何地都应该避免使用宏,即使它会导致更多的代码。
  • 宏不是必需的,它可以让我“压缩”必要的代码。尤其是只用于命名查找的空结构,只需要放置一次。

标签: c++ templates boost boost-preprocessor


【解决方案1】:

下面是应该起作用的东西:

#include <boost/fusion/container/map.hpp>
#include <boost/preprocessor.hpp>
#include <boost/signals2.hpp>

template <typename T> struct EventTraits;

#define DECLARE_EVENT_STRUCT(r, data, elem) struct BOOST_PP_TUPLE_ELEM(2,0,elem);
#define DECLARE_MAP_ITEM(r, data, i, elem) BOOST_PP_COMMA_IF(i) boost::fusion::pair<BOOST_PP_TUPLE_ELEM(2,0,elem), boost::signals2::signal<BOOST_PP_TUPLE_ELEM(2,1,elem)> >
#define CONSTRUCT_EVENTS_(Name, EventSeq)                          \
    class Name;                                                    \
    template <> struct EventTraits<Name>                           \
    {                                                              \
        BOOST_PP_SEQ_FOR_EACH(DECLARE_EVENT_STRUCT, _, EventSeq)   \
        typedef boost::fusion::map                                 \
        <                                                          \
            BOOST_PP_SEQ_FOR_EACH_I(DECLARE_MAP_ITEM, _, EventSeq) \
        > Events;                                                  \
    };                                                             \
/***/

//! Stuff to transform (A,B)(C,D) into ((A,B))((C,D)) so BOOST_PP_SEQ_FOR_EACH can be used. (sequence of tuples)
#define ADD_PAREN_1(A, B) ((A, B)) ADD_PAREN_2 
#define ADD_PAREN_2(A, B) ((A, B)) ADD_PAREN_1 
#define ADD_PAREN_1_END 
#define ADD_PAREN_2_END 
#define CONSTRUCT_EVENT(Name, EventSeq)                            \
CONSTRUCT_EVENTS_(Name, BOOST_PP_CAT(ADD_PAREN_1 EventSeq,_END))   \
/***/

//! Check the output (I use this on visual studio)
#pragma  message(BOOST_PP_STRINGIZE((CONSTRUCT_EVENT(SomeClass, (Started, void())(Finished, void(int))))))

//! Result (with formatting applied)
class SomeClass; 
template <> 
struct EventTraits<SomeClass> 
{
    struct Started; 
    struct Finished; 
    typedef boost::fusion::map 
        <
            boost::fusion::pair<Started, boost::signals2::signal<void()> >
          , boost::fusion::pair<Finished, boost::signals2::signal<void(int)> >
        > Events; 
};

int main()
{
    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-17
    • 2020-07-02
    • 2011-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多