2016-02-29 64 views
1

我已经得到了以下宏宏不是直接调用扩大,但扩大的间接

#include <boost/preprocessor.hpp> 

#define DB_FIELD(...) BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__) 

#define DB_TOFIELD(type,name) \ 
    private:\ 
    type name##_;\ 
    public:\ 
    const type& get_##name(){return name##_;}\ 
    void set_##name(const type& val) { name##_ = val; } 

#define GEN_ENUM_FIELD(r,data,elem) BOOST_PP_CAT(FIELD_,BOOST_PP_SEQ_ELEM(1,elem)), 

#define DECLARE(type, name) DB_TOFIELD(type, name) 

#define GEN_FIELD_DECL(r, data, elem) DECLARE(BOOST_PP_SEQ_ELEM(0,elem),BOOST_PP_SEQ_ELEM(1,elem)) 

#define DB_TABLE(name, ...) class name : public DataBaseTable {\ 
    public:\ 
    constexpr static const char *get_table_name() { return #name; }\ 
    BOOST_PP_LIST_FOR_EACH(GEN_FIELD_DECL,, BOOST_PP_VARIADIC_TO_LIST(__VA_ARGS__)) \ 
    enum Fields{ \ 
    BOOST_PP_LIST_FOR_EACH(GEN_ENUM_FIELD,, BOOST_PP_VARIADIC_TO_LIST(__VA_ARGS__))\ 
    FIELD_COUNT\ 
    };\ 
    }; 

现在下面的代码:

DB_TABLE(Test2, 
    DB_FIELD(int, foo), 
    DB_FIELD(int, bar) 
) 

生成:

class Test2 : public DataBaseTable { 
public: 
    constexpr static const char *get_table_name() { return "Test2"; } 
private: 
    int foo_; 
public: 
    const int &get_foo() { return foo_; } 
    void set_foo(const int &val) { foo_ = val; } 
private: 
    int bar_; 
public: 
    const int &get_bar() { return bar_; } 
    void set_bar(const int &val) { bar_ = val; } 
    enum Fields { FIELD_foo, FIELD_bar, FIELD_COUNT }; 
}; 

哪和我写的一样丑陋,但我的担心是为什么我需要这种间接性(DECLARE)GEN_FIELD_DECL宏?到DB_TOFIELD

#define GEN_FIELD_DECL(r, data, elem) DB_TOFIELD(BOOST_PP_SEQ_ELEM(0,elem),BOOST_PP_SEQ_ELEM(1,elem)) 

直接调用产生的垃圾:

class Test2 : public DataBaseTable { 
public: 
    constexpr static const char *get_table_name() { return "Test2"; } 
private: 
    int foo _; 
public: 
    const int &get_BOOST_PP_SEQ_ELEM(1, (int)(foo))() { return foo _; } 
    void set_BOOST_PP_SEQ_ELEM(1, (int)(foo))(const int &val) { foo _ = val; } 
private: 
    int bar _; 
public: 
    const int &get_BOOST_PP_SEQ_ELEM(1, (int)(bar))() { return bar _; } 
    void set_BOOST_PP_SEQ_ELEM(1, (int)(bar))(const int &val) { bar _ = val; } 
    enum Fields { FIELD_foo, FIELD_bar, FIELD_COUNT }; 
}; 

出现同样的问题重现铿锵3.7.1和gcc 5.3

回答

2

什么你正在运行到一个例外如果预处理器是参数###运算符,预处理器如何扩展参数。从C++ 2011 § 16.3.1 ¶ 1:

已经确定的参数为函数宏的调用后,参数替换 发生。在替换列表中的参数,除非前面由###预处理记号或 后跟一个##预处理记号(见下文),由对应的参数在其中已被扩展包含的所有的宏 后更换。在被替换之前,每个参数的预处理标记是 完全宏替换,就好像它们构成了预处理文件的其余部分一样;没有其他预处理令牌 可用。

宏间接避免了异常子句,导致参数在被另一个宏处理之前展开。

例如:

#define FOO 10 
#define BAR(x) x ## 7 
#define BAR2(x) BAR(x) 

int x = BAR(FOO);  // => int x = FOO7; 

int y = BAR2(FOO);  // => int y = BAR(10); (intermediate result) 
         // => int y = 107;  (final expansion)