The same code, one generated by macros and the other handwritten, produces different results.I'm lost and don't know how to fix it.
my environment is follow:
vs2019, msvc2019_64, c++14
- if using macros:
M(code,country)
it will error:
Illegal reference to non-static member "Addr::country"
- but if using handwritten:
it will success;
#define ARGS_FOREACH_1(f,_1) f(_1)
#define ARGS_FOREACH_2(f,_1,_2) f(_1) f(_2)
#define ARGS_FOREACH_3(f,_1,_2,_3) f(_1) f(_2) f(_3)
#define ARGS_FOREACH_4(f,_1,_2,_3,_4) f(_1) f(_2) f(_3) f(_4)
#define ARGS_FOREACH_5(f,_1,_2,_3,_4,_5) f(_1) f(_2) f(_3) f(_4) f(_5)
#define ARGS_FOREACH_6(f,_1,_2,_3,_4,_5,_6) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6)
#define ARGS_FOREACH_7(f,_1,_2,_3,_4,_5,_6,_7) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7)
#define ARGS_FOREACH_8(f,_1,_2,_3,_4,_5,_6,_7,_8) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8)
#define ARGS_FOREACH_9(f,_1,_2,_3,_4,_5,_6,_7,_8,_9) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9)
#define ARGS_FOREACH_10(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10)
#define ARGS_COUNT_IMPL(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,N,...) N
#define ARGS_RETURN_COUNT(...) ARGS_COUNT_IMPL(,##__VA_ARGS__,10,9,8,7,6,5,4,3,2,1,0)
#define CAT_MACRO_IMPL(x,y) x##y
#define CAT_MACRO_EXPAND(x,y) CAT_MACRO_IMPL(x,y)
#define ARGS_FOREACH(f,...) CAT_MACRO_EXPAND(ARGS_FOREACH_,ARGS_RETURN_COUNT(__VA_ARGS__))(f,__VA_ARGS__)
#define M_BEGIN() \
template <typename T,typename Func> \
static constexpr void for_each_members_struct(Func&& func){
#define M_BODY_MEMBER(name) \
func(#name,&T::name);
#define M_END() \
}
/*
* Mandatory
* optional
*/
#define M(...) \
M_BEGIN() \
ARGS_FOREACH(M_BODY_MEMBER,__VA_ARGS__) \
M_END()
struct Addr
{
int country;
int code;
/* error */
M(code,country)
/* pass*/
/*
template <typename T,typename Func>
static constexpr void for_each_members_struct(Func&& func){
func("code",&T::code);
func("country",&T::country);
}
*/
};
int main()
{
Addr d;
Addr::for_each_members_struct<Addr>([&](const char* name, auto v)
{
d.*v = 1;
});
std::cout << d.code;
std::cout << d.country;
}