C++宏仅在预处理为文件时有效

标签 c++ visual-c++ macros

我正在尝试为新的 std::optional<T> 创建匹配机制在 C++ 中。我写了下面的宏:

#define EXPAND(x) x
#define CAT_(x, y) x##y
#define CAT(x, y) CAT_(EXPAND(x), EXPAND(y))
#define if_opt__(xalt, bval, x, y)  \
auto xalt = y;                      \
bool bval = true;                   \
if (xalt.has_value())               \
for (auto x = xalt.value(); bval; bval = false)
#define if_opt_(xalt, x, y) if_opt__(xalt, CAT(xalt, _b), x, y)
#define if_opt(x, y) if_opt_(CAT(x, __LINE__), x, y)

我已经为它创建了以下示例程序:

std::optional<int> get(int a) {
    if (a < 0) {
        return {};
    }
    return a;
}

int main(void) {
    if_opt(a, get(0)) {
        std::cout << "optional matched!" << std::endl;
    }
    return 0;
}

但是,当我尝试编译该程序时,出现了诸如“重新定义;”之类的错误。不同的基本类型'。然后我将它预处理到一个文件,复制结果并编译并工作得很好。宏评估为:

auto a24 = get(0);
bool a24_b = true;
if (a24.has_value()) 
    for (auto a = a24.value(); a24_b; a24_b = false) {
        std::cout << "optional matched!" << std::endl;
    }

为什么不使用宏本身进行编译?我正在使用 MSVC。

最佳答案

应该更正您的 CAT 宏执行额外扩展的方式:

//#define EXPAND(x) x // not needed
#define CAT_(x, y) x##y
#define CAT(x, y) CAT_(x, y)

当它在某个点被扩展时,它会产生表达式 EXPAND(x)##EXPAND(y) 这会中断进一步的扩展,因为 ## 只能使用普通标记,甚至不会尝试展开EXPAND

为什么它在预处理文件时有效?可能是因为 VS 有非常奇特的(和不符合规范的)处理方式。即使在对文件进行预处理时,Gcc 也会为您提供更好的诊断。

关于C++宏仅在预处理为文件时有效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43576311/

相关文章:

c++ - C++ : ScopeGuard vs return check and exception handling?

c++ - 如何使模板类型推导与引用一起工作?

c++ - 在 chrome native 客户端中运行 C++ Windows 窗体

ios - Objective-C: "format string is not a string literal (potentially insecure)"宏警告

c++ - 在 64 位机器中无法使用 getsystemdirectory() 获取正确的路径

c++ - 如何在 Qt 中监听 QDynamicPropertyChangeEvent 来检测属性变化?

c - 二维数组的 malloc 在 GCC 中有效,但在 Visual C++ 中无效

c++ - 如何从 boost::split 获取多个参数

c - 什么时候应该使用宏而不是内联函数?

字符串化变量的 C 宏