C++ 宏不是用直接调用展开的,而是用间接调用展开的
我有以下宏C++ 宏不是用直接调用展开的,而是用间接调用展开的,c++,macros,variadic-macros,boost-preprocessor,C++,Macros,Variadic Macros,Boost Preprocessor,我有以下宏 #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(con
#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\
};\
};
生成:
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 };
};
这和我写的一样难看,但我关心的是为什么在GEN_字段DECL宏中需要这种级别的间接寻址(DECLARE)?直接调用DB\u-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 };
};
clang 3.7.1和gcc 5.3再现了相同的行为。如果参数是
#
或#
运算符的参数,则预处理器如何扩展参数是一个例外。从C++ 2011节16.3.1i 1:
在确定了调用函数(如宏)的参数后,将进行参数替换
发生了。替换列表中的参数,,除非前面有#
或#
预处理令牌或
后跟一个##
预处理标记(见下文),在所有宏之后替换为相应的参数
其中所载内容已扩大。在被替换之前,每个参数的预处理标记都是
完全替换宏,就好像它们构成了预处理文件的其余部分一样;没有其他预处理标记
都有
宏间接避免使用exception子句,使参数在被另一个宏处理之前展开
例如:
#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)
#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)