C++ 强制预处理器在重新定义中使用以前的定义

C++ 强制预处理器在重新定义中使用以前的定义,c++,g++,c-preprocessor,boost-preprocessor,C++,G++,C Preprocessor,Boost Preprocessor,更新3: 没关系。我得到了我想要的东西。下面给出了类内部的唯一标识符 static const int _counter_start = __COUNTER__; static const int val1 = __COUNTER__ - _counter_start; static const int val2 = __COUNTER__ - _counter_start; 更新2: 我将用这个功能实现类似于消息映射的东西 class a { ... MAP_BEGIN()

更新3:

没关系。我得到了我想要的东西。下面给出了类内部的唯一标识符

static const int _counter_start = __COUNTER__;
static const int val1 = __COUNTER__ - _counter_start;
static const int val2 = __COUNTER__ - _counter_start;
更新2:

我将用这个功能实现类似于消息映射的东西

class a
{
...
    MAP_BEGIN()
    MAP_DECL...
    MAP_END()
...
};
问题是,对于每个MAP_DECL,我需要在两个地方展开宏

class a
{    
    virtual void func()
    {        
        ...
        //does something with the decl declaration        
    }
    ...
    //also expand some stuff here    
}
Boost预处理器(理论上)应该允许我将MAP_DECL累积到一个序列中,并在最后将其扩展为func()(同时在执行时扩展类字段)


更新1:

我现在正在使用Boost预处理器库。每次我需要向序列中添加一些内容时,我都会创建一个新的宏变量/定义,如下所示

我正在尝试扩展Boost预处理器序列,但目前我一直在这样做

#define SEQ (w)(x)(y)(z) 
#define SEQ2 BOOST_PP_SEQ_PUSH_BACK(SEQ, a)

原件:

假设我有以下代码

#define CUR 2
#define CUR CUR + 2
如何强制第二行使用第一行的CUR值?

简而言之,您不能


在扩展CUR时(在第二个
#define
之后),预处理器将用CUR+2替换CUR的实例,并“蓝色绘制”CUR的名称(不再扩展它)。此后,C编译器会看到CUR+2,这很可能会产生编译错误。

你不能这样做,你只能定义每个宏一次,否则编译器将溢出一个错误。

即使你可以这样做,也是危险的。
例如:

#define CUR 2
#define CUR CUR + 2
...
int x = CUR*4; // x = 2 + 2 * 4

我曾尝试做过类似的事情(添加boost预处理器序列)。我狠狠地撞了墙(因为乔纳森在回答中说了些什么),结果做了完全不同的事情

后来我发现boostmpl类型的序列也有同样的有效限制(这完全有道理,但有时你直到真正撞到它时才会看到墙:)

您几乎必须定义整个序列,或者给它起不同的名称

您可能正在定义某个成员变量,然后在函数中使用它(注册?)。如果您将消息保存在一个容器中,您可以让您的MAP_DECL向其中添加一条消息,然后在函数中执行for循环

#define MAP_BEGIN std::vector<Message> m_messages; \
  void buildMap() {
#define MAP_END }
#define MAP_DECL(...) m_messages.push_back(...);
#定义映射开始std::向量m#u消息\
void buildMap(){
#定义映射_END}
#定义MAP_DECL(…)m_消息;

如果每条消息都是单独的类型,请尝试类型擦除(boost::any)或使它们从某个基类继承并存储。

为什么要尝试这样做?谢谢。哇,我的拼写很差。即使(也许特别是)有了更新,我也很难想象你想要实现什么。首先,括号中的w,x,y,z部分让我难以置信。然后,在不知道BOOST_PP_SEQ_PUSH_BACK()应该做什么的情况下,我只能猜测SEQ2可能会扩展到理想世界中的“(w)(x)(y)(z)(a)”。SEQ或SEQ2没有明确的参数,这似乎有点奇怪——这通常是不受欢迎的宏处理的迹象。但这是一个很大的猜测-你能扩展你的更新,以更准确地显示你想要达到的效果吗?在第二次更新后…你确定你应该尝试(ab?)像这样使用预处理器吗?你确信你不能在C++中使用模板来达到预期的效果吗?为什么要通过宏来构建类主体?用户会写什么?用户(程序员)会写#define MAP_BEGIN()。。。和#定义地图#定义。。。和#define MAP_END()。。。然后您的代码将使用这些定义来编写类?好的,现在要使用类,用户必须在3个不同的位置声明这个映射(一次静态声明消息,一次注册消息,一次在实现中定义消息)。宏将驻留在另一个头文件中,而用户只是在使用它们。您可以这样做。至少当GCC处于默认模式时,您只需得到一个关于非良性宏重新定义的警告,但重新定义的值将生效
#define x1/#define x2/int main(){return X;}
(使用/表示新行)。在MacOS X上,我得到了两行警告数据(尽管可以说只是一条警告);程序链接并运行并生成退出状态2。预处理器的输出为:
intx=CUR+2*4通常不会编译,因为没有变量CUR的定义。@Jonathan Leffler,我假设预处理器将CUR重新定义为
2+2
没有问题,如果您编写:#为第二个实例定义CUR 2+2,那么编译器可能会发出一点声音(警告),但它会工作。然后你关于缺少括号的警告,如果拼写出来,将是有效的。但这并不是问题的初衷——不完全是。(而且,我承认,在两次更新之后,我不再确定现在的问题是什么。)我以前试过,但没有成功,因为我必须在函数的作用域中注册,同时在类的作用域中声明内容。