【问题标题】:Keep track of macro expansion跟踪宏扩展
【发布时间】:2012-03-19 13:04:42
【问题描述】:

我想跟踪宏扩展 - 宏扩展了多少次,扩展发生时的 args 是什么。

例如,

我有一个宏可能看起来像这样:

#define mymacro(x) int x

在我的代码中我有这样的东西:

mymacro(a);
mymacro(b);

在预处理器扩展结束时(哦,是的,有没有办法让特定的宏成为最后一个扩展?),我想知道 mymacro 被使用了多少次,传递的 args 是什么.在这种情况下,它将是 2 次,并且 args 将是 a 和 b。

我正在研究 boost-preprocessor lib。他们有 BOOST_PP_ARRAY,但我不知道如何将其设为“静态”,以便以后使用。

我在 BOOST_PP_COUNTER 中找到了一些东西。看起来 BOOST_PP_COUNTER 是可以在预处理器短语中保持其状态的东西。但我仍然不清楚如何做我想做的事。

【问题讨论】:

  • 这可以通过在宏中添加一行来输出编译器消息来完成,如果你的编译器支持的话。
  • 你能说得更具体点吗?我正在使用 Clang
  • 我还不是很清楚,但是您正在谈论过去对正在发生的事情的检查,并希望结果(即,它被调用的内容等)在预处理时可用,以便您可以用它做点什么,对吧?
  • 是的,这就是我想做的事
  • 我希望你不要期望这个计数会在编译单元中保持...

标签: c++ macros boost-preprocessor


【解决方案1】:

这样的事情怎么样?

#include <iostream>

int m_counter = 0;
const char *m_arguments[32] = { 0 };

#define COUNT_M(a) m_arguments[m_counter++] = #a;
#define M(a) COUNT_M(a) int a

int main()
{
    M(x);
    M(y);

    for (int i = 0; i < m_counter; i++)
    {
        std::cout << "m_arguments[" << i << "] = \"" << m_arguments[i] << "\"\n";
    }
}

【讨论】:

  • hmm... 在这种情况下,需要在运行时调用 M(x) 和 M(y) 才能工作。我的 marcos 是回调,因此不必调用它。无论如何要在编译时执行此操作?
【解决方案2】:

我不太确定您的最终目标是什么,但您可以使用活动参数跟踪扫描次数(而不是扩展次数)。每次预处理器扫描活动参数时都会扩展它。例如,

#define EMPTY()

#define A(n) \
    A_INDIRECT EMPTY()()(BOOST_PP_INC(n)) 

#define A_INDIRECT() A

#define X(arg) arg
#define Y(arg) X(arg)
#define Z(arg) Y(arg)

   A(0)   // A_INDIRECT()(1)
X( A(0) ) // A_INDIRECT()(2)
Y( A(0) ) // A_INDIRECT()(3)
Z( A(0) ) // A_INDIRECT()(4)

对 A 的每次调用都会经过不同次数的扫描,从而导致每次的结果都不同。

宏不能影响全局状态。实现某种状态的唯一其他方法是使用递归。请记住,宏不会递归扩展,因此预处理器会跟踪此状态。它是唯一可能受宏影响的“全局”状态。但是,它可能难以控制。宏必须强制在某个递归级别扩展,每个级别都有一个宏,并且需要某种形式的二进制搜索来有效地读取“状态”。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-30
    相关资源
    最近更新 更多