C++ 带有可变参数的嵌套宏在GCC中编译,但不在MSVC中编译

C++ 带有可变参数的嵌套宏在GCC中编译,但不在MSVC中编译,c++,c,gcc,visual-c++,macros,C++,C,Gcc,Visual C++,Macros,我用boost/预处理器创建了一个宏,以重复创建代码。这是因为我在一个非常受限的目标硬件上工作,并且有一个非常受限的编译器,它不支持数组 我提出的代码如下: #定义ESC(…)(变量)__ #定义IF_BODY(n、条件、左侧、右侧、arg1、arg2)\ 如果(条件>n){\ lhs##n.arg1=rhs[n].arg1\ lhs##n.arg2=rhs[n].arg2\ } #定义IF_BODY(A,B)IF_BODY(A,B) #定义IF_查询(z,n,vars)IF_主体(n,ESC

我用boost/预处理器创建了一个宏,以重复创建代码。这是因为我在一个非常受限的目标硬件上工作,并且有一个非常受限的编译器,它不支持数组

我提出的代码如下:

#定义ESC(…)(变量)__
#定义IF_BODY(n、条件、左侧、右侧、arg1、arg2)\
如果(条件>n){\
lhs##n.arg1=rhs[n].arg1\
lhs##n.arg2=rhs[n].arg2\
}
#定义IF_BODY(A,B)IF_BODY(A,B)
#定义IF_查询(z,n,vars)IF_主体(n,ESC vars)
BOOST_PP_REPEAT(3,如果有疑问\
(索引、变量名称、其他变量名称、纬度、经度))
它的目的是创建几个具有递增条件的if查询

我用gcc在godbolt上测试了这段代码,它就像一个符咒一样工作。 现在,当我在MSVC中尝试同样的方法时,它不会编译。错误为C2065,例如未声明“variableName”


为什么呢?这是MSVC中的一个bug吗?MSVC不支持这些类型的宏吗?我的代码中有错误吗?

我的调查让我相信这是MSVC中的错误

如果我将代码更改为以下内容并对文件进行预处理(请注意,我的'coord'和'variableName','otherVariableName'标识符只是为了使代码的这些部分与某些内容匹配,并且请注意我如何颠倒了If_BODY和If_BODY,以及If_BODY_u被#If 0注释掉):

请注意,宏调用具有正确数量的参数。但是,如果将#if 0更改为#if 1,则会得到以下编译器输出: tester\tester.cpp(35):警告C4003:没有足够的参数用于诸如宏调用“IF_BODY”之类的函数

查看这种情况下的预处理结果:

int main()
{
    int index;
    coord variableName0, otherVariableName0;
    coord variableName1, otherVariableName1;
    coord variableName1, otherVariableName1;
    if (index, variableName, otherVariableName, latitude, longitude > 0) { 0. = [0].; 0. = [0].; } 
    if (index, variableName, otherVariableName, latitude, longitude > 1) { 1. = [1].; 1. = [1].; } 
    if (index, variableName, otherVariableName, latitude, longitude > 2) { 2. = [2].; 2. = [2].; }
}
MSVC似乎在执行ESC展开之前执行宏变量赋值,B的所有内容都被赋值为“条件”,而不是被分解为正确的IF_BODY_参数。我将通过MSVS帮助->发送反馈->报告问题机制将此作为反馈提交

--

好吧,我已经找到了一个解决办法,但它非常难看。它需要对BOOST_PP_REPEAT族进行可变扩展(我在这里只实现了一部分)。可能值得将此作为boost的建议提交,但我不确定boost.preprocessor是否仍然保持。请注意,在此版本中,ESC/ESC宏是如何消失的

#include <boost/preprocessor/repeat.hpp>

# define BOOST_PP_REPEAT_1_1_V(m, d, ...) m(2, 0, d, __VA_ARGS__)
# define BOOST_PP_REPEAT_1_2_V(m, d, ...) BOOST_PP_REPEAT_1_1_V(m, d, __VA_ARGS__) m(2, 1, d, __VA_ARGS__)
# define BOOST_PP_REPEAT_1_3_V(m, d, ...) BOOST_PP_REPEAT_1_2_V(m, d, __VA_ARGS__) m(2, 2, d, __VA_ARGS__)
# define BOOST_PP_REPEAT_1_4_V(m, d, ...) BOOST_PP_REPEAT_1_3_V(m, d, __VA_ARGS__) m(2, 3, d, __VA_ARGS__)
# define BOOST_PP_REPEAT_1_I_V(c, m, d, ...) BOOST_PP_REPEAT_1_ ## c##_V(m, d, __VA_ARGS__)
# define BOOST_PP_REPEAT_1_V(c, m, d, ...) BOOST_PP_REPEAT_1_I_V(c, m, d, __VA_ARGS__)

#define BOOST_PP_REPEAT_V BOOST_PP_CAT(BOOST_PP_CAT(BOOST_PP_REPEAT_, BOOST_PP_AUTO_REC(BOOST_PP_REPEAT_P, 4)), _V)


struct coord
{
    int latitude, longitude;
};

#if 1
# define IF_BODY_(n, condition, lhs, rhs, arg1, arg2) \
if (condition > n) { \
    lhs##n.arg1 = rhs[n].arg1; \
lhs##n.arg2 = rhs[n].arg2; \
}
#endif

#define ESC_(...) __VA_ARGS__
#define ESC(a) ESC_(a)
#define IF_BODY(a, ...) ESC_(IF_BODY_(a, __VA_ARGS__))
# define IF_QUERY(z, n, ...) IF_BODY(n, __VA_ARGS__)


int main()
{
    int index = 0;
    coord variableName0, variableName1, variableName2;
    coord otherVariableName[3];

    BOOST_PP_REPEAT_V(3, IF_QUERY, index, variableName, otherVariableName, latitude, longitude)
}

不过,您很可能不知道,您可以告诉编译器资源管理器将boost添加为库。看看伊科尼知道的那本书。但我手动添加了标题,以检查问题是否与godbolt有关。这就是问题的结局。很抱歉造成混淆,谢谢您的推荐。非常感谢您的调查!你认为有办法绕过这个错误吗?看看我的扩展答案,我确实找到了解决这个问题的方法。但就像我说的,它很难看。更好的方法可能是使用编译器(甚至是gcc),而不是使用boost预处理器的元组宏(这也需要去掉ESC,以便将分组的参数作为一个单元传递)。很好!同样感谢TUPLE宏的提示,我现在使用它,它就像一个符咒。
int main()
{
    int index;
    coord variableName0, otherVariableName0;
    coord variableName1, otherVariableName1;
    coord variableName1, otherVariableName1;
    if (index, variableName, otherVariableName, latitude, longitude > 0) { 0. = [0].; 0. = [0].; } 
    if (index, variableName, otherVariableName, latitude, longitude > 1) { 1. = [1].; 1. = [1].; } 
    if (index, variableName, otherVariableName, latitude, longitude > 2) { 2. = [2].; 2. = [2].; }
}
#include <boost/preprocessor/repeat.hpp>

# define BOOST_PP_REPEAT_1_1_V(m, d, ...) m(2, 0, d, __VA_ARGS__)
# define BOOST_PP_REPEAT_1_2_V(m, d, ...) BOOST_PP_REPEAT_1_1_V(m, d, __VA_ARGS__) m(2, 1, d, __VA_ARGS__)
# define BOOST_PP_REPEAT_1_3_V(m, d, ...) BOOST_PP_REPEAT_1_2_V(m, d, __VA_ARGS__) m(2, 2, d, __VA_ARGS__)
# define BOOST_PP_REPEAT_1_4_V(m, d, ...) BOOST_PP_REPEAT_1_3_V(m, d, __VA_ARGS__) m(2, 3, d, __VA_ARGS__)
# define BOOST_PP_REPEAT_1_I_V(c, m, d, ...) BOOST_PP_REPEAT_1_ ## c##_V(m, d, __VA_ARGS__)
# define BOOST_PP_REPEAT_1_V(c, m, d, ...) BOOST_PP_REPEAT_1_I_V(c, m, d, __VA_ARGS__)

#define BOOST_PP_REPEAT_V BOOST_PP_CAT(BOOST_PP_CAT(BOOST_PP_REPEAT_, BOOST_PP_AUTO_REC(BOOST_PP_REPEAT_P, 4)), _V)


struct coord
{
    int latitude, longitude;
};

#if 1
# define IF_BODY_(n, condition, lhs, rhs, arg1, arg2) \
if (condition > n) { \
    lhs##n.arg1 = rhs[n].arg1; \
lhs##n.arg2 = rhs[n].arg2; \
}
#endif

#define ESC_(...) __VA_ARGS__
#define ESC(a) ESC_(a)
#define IF_BODY(a, ...) ESC_(IF_BODY_(a, __VA_ARGS__))
# define IF_QUERY(z, n, ...) IF_BODY(n, __VA_ARGS__)


int main()
{
    int index = 0;
    coord variableName0, variableName1, variableName2;
    coord otherVariableName[3];

    BOOST_PP_REPEAT_V(3, IF_QUERY, index, variableName, otherVariableName, latitude, longitude)
}
int main()
{
    int index = 0;
    coord variableName0, variableName1, variableName2;
    coord otherVariableName[3];

    if (index > 0) { variableName0.latitude = otherVariableName[0].latitude; variableName0.longitude = otherVariableName[0].longitude; } 
    if (index > 1) { variableName1.latitude = otherVariableName[1].latitude; variableName1.longitude = otherVariableName[1].longitude; } 
    if (index > 2) { variableName2.latitude = otherVariableName[2].latitude; variableName2.longitude = otherVariableName[2].longitude; }
}