5

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;
}
New contributor
user31892351 is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
3
  • @MarekR, from the question it seems that the actual behavior is that the compiler reports an error and that the desired behavior is that the macro compiles the same as the "handwritten" code (i.e. the macro should evaluate to the commented-out code). Commented Nov 17 at 9:03
  • 1
    the title seems to be unrelated to the question. The issue is a compiler error, not that it takes longer Commented Nov 17 at 9:35
  • I agree the title did not match the question. It still doesn't after the edit: it's not that the same code gives different results, but the macro does not expand to the expected code. The title should describe (preferably in one line) what the OP tries to achieve. Commented Nov 17 at 10:12

1 Answer 1

10

MSVC by default uses a non-conforming preprocessor. Your code works correctly if the conforming preprocessor is enabled using /Zc:preprocessor: https://godbolt.org/z/oWcq1ds4r

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.