【问题标题】:Force Preprocessor to use a previous definition in a redefinition强制预处理器在重新定义中使用先前的定义
【发布时间】:2010-11-25 23:27:12
【问题描述】:

更新 3

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

static const int _counter_start = __COUNTER__;
static const int val1 = __COUNTER__ - _counter_start;
static const int val2 = __COUNTER__ - _counter_start;

更新 2

Boost Preprocessor

我将使用此功能实现类似于消息映射的东西。

class a
{
...
    MAP_BEGIN()
    MAP_DECL...
    MAP_END()
...
};

问题是,对于每个 MAP_DECL,我需要在 2 个地方扩展宏。

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 值?

【问题讨论】:

  • 你为什么要这样做?
  • 谢谢乔纳森。哇,我拼写不好。
  • 即使(或者可能特别是)更新到位,我发现很难想象你想要实现什么。对于初学者来说,括号中的 w, x, y, z 部分让我难以置信。然后,在不知道 BOOST_PP_SEQ_PUSH_BACK() 应该做什么的情况下,我只能猜测 SEQ2 在您的理想世界中可能会扩展为 '(w)(x)(y)(z)(a)'。 SEQ 或 SEQ2 没有明确的参数似乎有点奇怪 - 这通常表明不需要的宏处理。但这是很多猜测 - 您能否扩展您的更新以更准确地显示您想要实现的效果?
  • 第二次更新后...你确定你应该尝试(ab?)像这样使用预处理器吗?你确定不能在 C++ 中使用模板来达到预期的效果吗?为什么要通过宏构建类体?用户会写什么?用户(程序员)会写#define MAP_BEGIN() ...和#define MAP_DECL ...和#define MAP_END() ...然后您的代码将使用这些定义来编写类吗?
  • 好吧,现在要使用这个类,用户必须在 3 个不同的地方声明这个映射(一次是静态声明消息,一次是注册它,一次是在实现中定义它)。宏将驻留在另一个头文件中,用户只是在使用它们。

标签: c++ g++ c-preprocessor boost-preprocessor


【解决方案1】:

简而言之,你不能。

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

【讨论】:

    【解决方案2】:

    即使你能做到,那也是危险的。
    示例:

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

    【讨论】:

    • 预处理器的输出是:int x = CUR + 2*4;,通常不会编译,因为没有定义变量 CUR。
    • @Jonathan Leffler,我认为预处理器将 CUR 重新定义为 2 + 2 没有问题
    • 如果你写了:#define CUR 2+2 用于第二个实例,那么编译器可能会抱怨一点(警告),但它会起作用。然后你关于缺少括号的警告,如果拼写出来,将是有效的。但这不是问题最初要问的——不完全是。 (而且,我承认,在两次更新之后,我不再确定 现在问的是什么问题。)
    【解决方案3】:

    你不能这样做,你只能#define每个宏一次,否则编译器会溢出错误。

    【讨论】:

    • 你可以这样做。至少在默认模式下使用 GCC,您只会收到有关非良性宏重新定义的警告,但重新定义的值会生效。 #define X 1 / #define X 2 / int main(){return X;}(使用 / 表示新行)。在 MacOS X 上,我得到 2 行警告数据(尽管可以说它只是一个警告);程序链接并运行并生成退出状态 2.
    【解决方案4】:

    我曾尝试在某一时刻做类似的事情(附加到增强预处理器序列)。我狠狠地撞了墙(因为乔纳森在他的回答中所说的话),最终做了完全不同的事情。

    后来我发现 boost MPL 类型序列具有相同的有效限制(这完全有道理,但有时你直到真正碰到它才看到一堵墙 :))。

    你几乎必须定义整个序列或给它不同的名字。

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

    #define MAP_BEGIN std::vector<Message> m_messages; \
      void buildMap() {
    #define MAP_END }
    #define MAP_DECL(...) m_messages.push_back(...);
    

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

    【讨论】:

    • 我之前尝试过,但没有成功,因为我必须在函数范围内注册,同时在类范围内声明内容。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-27
    • 1970-01-01
    • 2021-12-29
    相关资源
    最近更新 更多