我想编写一个简单的Macro函数。由于此宏在许多地方由不同的常规c ++函数使用,因此遇到了可变范围问题。我想知道是否有快速的解决方法?非常感谢。
您可以在所附的代码中看到,取决于是否在函数中第一次调用该宏,我想声明或重用变量ptrCandidate
。请注意,变量作用域在函数中,而不在文件或翻译单元中。换句话说,每次在新函数中第一次调用该宏时,我都希望使用顶部宏。在同一函数中,如果再次调用该宏,则需要底部宏。
#define EXPECT_MY_CLASS_EQ(expectedStr, candidateStr) \
auto ptrCandidate = parseAndGetPtr(candidateStr); \
doWork(ptrCandidate); \
EXPECT_EQ(expectedStr, convertToString(ptrCandidate));
#define EXPECT_MY_CLASS_EQ(expectedStr, candidateStr) \
ptrCandidate = parseAndGetPtr(candidateStr); \
doWork(ptrCandidate); \
EXPECT_EQ(expectedStr, convertToString(ptrCandidate));
void foo(){
EXPECT_MY_CLASS_EQ("123","abcd")
}
void bar(){
EXPECT_MY_CLASS_EQ("111","aabb")
EXPECT_MY_CLASS_EQ("222","ccdd")
}
void foo(){
auto ptrCandidate = parseAndGetPtr("abcd");
doWork(ptrCandidate);
EXPECT_EQ("123", convertToString(ptrCandidate));
}
void bar(){
auto ptrCandidate = parseAndGetPtr("aabb");
doWork(ptrCandidate);
EXPECT_EQ("111", convertToString(ptrCandidate));
/* auto */ ptrCandidate = parseAndGetPtr("ccdd");
doWork(ptrCandidate);
EXPECT_EQ("222", convertToString(ptrCandidate));
}
答案 0 :(得分:4)
如另一个答案所示,在这种情况下,您不需要宏。
不过,一般来讲,您可以通过以下方式避免重新定义变量名:
使用__LINE__
预处理符号(或__COUNTER__
,尽管IIRC不是标准符号)。请注意,creating a variable name with the preprocessor requires two levels of indirection(将VARIABLE
替换为__LINE__
的链接)。
A do { /* code */ } while(0)
...这是AFAIK编写不仅仅是简单表达式的宏的最常用方法。
一个立即执行的lambda:
([](auto var) { /* code using var */ })(initExpressionForVar())
请注意,每种方法实际上每次都会创建一个 new 变量,因此在语义上与您使用两个单独的宏的方法有所不同!如果(assigned)变量的类型具有非默认赋值运算符,这一点尤其重要!
如果由于某种原因,您依赖于单个变量的重用和对其的赋值,那么IMO最简单的方法是定义两个宏。一个宏声明该变量(并在必要时对其进行初始化),另一个宏声明使用该变量的代码。
答案 1 :(得分:2)
似乎常规功能有效:
void EXPECT_MY_CLASS_EQ(const char* expectedStr, const char* candidateStr)
{
auto ptrCandidate = parseAndGetPtr(candidateStr);
doWork(ptrCandidate);
EXPECT_EQ(expectedStr, convertToString(ptrCandidate));
}
答案 2 :(得分:0)
一种可能的方法可能是将fillRect()
或__LINE__
与预处理符号concatenation一起使用。
在您的情况下,您可能不需要任何宏:希望使用一些__COUNTER__
函数。
这是我的Bismon项目文件cmacros.h line 285中的一个真实示例(使用串联和static inline
)(在C语言中,但是相同的技巧可以在C ++)
__LINE__
回到您的问题,如果您仍然需要宏:只需创建一个块,例如
#define LOCAL_FAILURE_HANDLE_ATBIS_BM(Fil,Lin,Lockset,Flabel,FcodVar,ReasonVar,PlaceVar) \
struct failurehandler_stBM fh_##Lin \
= { \
.pA = {.htyp = typayl_FailureHandler_BM}, \
.failh_magic = FAILUREHANDLEMAGIC_BM, \
.failh_lockset = Lockset, \
.failh_reason = NULL, \
.failh_jmpbuf = {}}; \
curfailurehandle_BM = &fh_##Lin; \
volatile int failcod_##Lin = setjmp(fh_##Lin.failh_jmpbuf); \
FcodVar = failcod_##Lin; \
if (failcod_##Lin) { \
ReasonVar = fh_##Lin.failh_reason; \
PlaceVar = fh_##Lin.failh_place; \
goto Flabel; \
}; \
(void)0
#define LOCAL_FAILURE_HANDLE_AT_BM(Fil,Lin,Lockset,Flabel,FcodVar,ReasonVar,PlaceVar) \
LOCAL_FAILURE_HANDLE_ATBIS_BM(Fil,Lin,Lockset,Flabel,FcodVar,ReasonVar,PlaceVar)
/// code using LOCAL_FAILURE_HANDLE_BM should probably backup and
/// restore the curfailurehandle_BM
#define LOCAL_FAILURE_HANDLE_BM(Lockset,Flabel,FcodVar,ReasonVar,PlaceVar) \
LOCAL_FAILURE_HANDLE_AT_BM(__FILE__,__LINE__,Lockset,Flabel,FcodVar,ReasonVar,PlaceVar)