如何避免使用C ++宏重新声明变量

时间:2019-04-17 22:11:02

标签: c++ macros

我想编写一个简单的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));
}

3 个答案:

答案 0 :(得分:4)

如另一个答案所示,在这种情况下,您不需要宏。

不过,一般来讲,您可以通过以下方式避免重新定义变量名:

请注意,每种方法实际上每次都会创建一个 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)