2

下面的代码说明了我遇到的问题。

#include <iostream>

#define X 4

int main()
{

    std::cout << "should be 4: " << X << std::endl;
#define Y X + 4
    std::cout << "should be 8: " << Y << std::endl;

#undef Y
#define Y X+0
#undef X
#define X Y+1

    std::cout << "expecting 5: " << X << std::endl;
}

错误:

test2.cc: In function ‘int main()’:
test2.cc:17: error: ‘X’ was not declared in this scope

我试图模拟的模式是在代码/构建级别扩展程序(很像nginx模块在编译时的连接方式)。我需要构建一个可扩展的编译时结构,通过将#includes 添加到我的构建中,它是可扩展的(可插入的),这会产生一个具有唯一名称的 boost-mpl-vector,其中包含我所有的插件。因此,如果X是唯一的结束名称,则 X_0、X_1、X_2 是在向量应用了 mpl-vector 时沿途建立的名称push_back

知道boost::preprocessor 的抽象是关键,但我还不想花时间研究它,因为我正在对系统的一部分进行原型设计,最终将在编译时模块化。

所以,为了以后的参考,

  1. 为什么我在上面收到错误?
  2. 正确的原始预处理器模式应该是什么样子。
  3. 正确的 boost-preprocessor-library 模式是什么样的。
4

3 回答 3

5

用 g++ -E 编译给出了这个:

int main()
{

    std::cout << "should be 4: " << 4 << std::endl;

    std::cout << "should be 8: " << 4 + 4 << std::endl;






    std::cout << "expecting 5: " << X+0 +1 << std::endl;
}

所以你可以看到为什么你会得到错误。

于 2011-04-08T09:19:53.040 回答
4

为什么不用一块石头杀死两只鸟并使用名称空间。

// a.hpp:

namespace a {
    const int module_id = 0;

    class module_a : extension_module< module_id > { … };
}

#undef last_module
#define last_module a

// b.hpp:

namespace b {
    const int last = last_module::module_id + 1;

    class module_b : extension_module< module_id > { … };
}

#undef last_module
#define last_module b

这不那么“聪明”,并留下了ID的痕迹。

但是,每次 ODR 都需要以相同的顺序包含这些模块才能正常工作。

我不主张杀死任何鸟类。

于 2011-04-08T09:15:32.490 回答
2

您的代码示例的问题是您在 X 和 Y 宏中有循环依赖:

Y定义为X+0,X定义为Y+1。所以当宏被扩展时(发生在你使用 X 的地方)你就会遇到问题。

添加:

似乎行为是这样的:X在其定义名称中扩展宏时 X 未在预处理器名称空间中定义,因此您将 X+0+1 视为 X 扩展。

于 2011-04-08T09:26:36.803 回答