gpt4 book ai didi

c++ - 具有可变参数的嵌套宏在 GCC 中编译但在 MSVC 中不编译

转载 作者:行者123 更新时间:2023-11-28 04:19:02 28 4
gpt4 key购买 nike

我用 boost/preprocessor 创建了一个宏来重复创建代码。这样做的原因是我使用非常受限的编译器在非常受限的目标硬件上工作,它不支持数组。

我想出的代码如下:

# define ESC(...) __VA_ARGS__
# define IF_BODY(n, condition, lhs, rhs, arg1, arg2) \
if (condition > n) { \
lhs##n.arg1 = rhs[n].arg1; \
lhs##n.arg2 = rhs[n].arg2; \
}
# define IF_BODY_(A, B) IF_BODY(A, B)
# define IF_QUERY(z, n, vars) IF_BODY_(n, ESC vars)

BOOST_PP_REPEAT(3, IF_QUERY, \
(index, variableName, otherVariableName, latitude, longitude))

它的目的是创建多个具有升序条件的 if 查询。

我用 gcc 在 godbolt 上测试了这段代码,它就像一个魅力一样工作,你可以 see here .现在,当我在 MSVC 中尝试相同的操作时,它无法编译。错误是C2065,例如“变量名”未声明。 See it here on godbolt .

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

最佳答案

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

如果我将代码更改为以下内容并对文件进行预处理(注意我的'coord'和'variableName','otherVariableName'标识符只是为了让你的代码的那些部分匹配某些东西,并注意如何我已经颠倒了你的 IF_BODY 和 IF_BODY_ 并且 IF_BODY_ 被 #if 0 注释掉了):

#include <boost/preprocessor/repeat.hpp>

struct coord
{
int latitude, longitude;
};

# define ESC_(...) __VA_ARGS__
#define ESC(vars) ESC_ vars

#if 0
# 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 IF_BODY(A, B) IF_BODY_(A, ESC(B))

# define IF_QUERY(z, n, vars) IF_BODY(n, vars)

int main()
{
int index;
coord variableName0, otherVariableName0;
coord variableName1, otherVariableName1;
coord variableName1, otherVariableName1;
BOOST_PP_REPEAT(3, IF_QUERY, (index, variableName, otherVariableName, latitude, longitude))
}

我得到以下信息:

int main()
{
int index;
coord variableName0, otherVariableName0;
coord variableName1, otherVariableName1;
coord variableName1, otherVariableName1;
IF_BODY_(0, index, variableName, otherVariableName, latitude, longitude)
IF_BODY_(1, index, variableName, otherVariableName, latitude, longitude)
IF_BODY_(2, index, variableName, otherVariableName, latitude, longitude)
}

请注意,宏调用具有正确数量的参数。但是,如果我将 #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.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)
}

新代码扩展为:

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; }
}

关于c++ - 具有可变参数的嵌套宏在 GCC 中编译但在 MSVC 中不编译,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55883451/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com