C++ 跟踪宏观扩张

C++ 跟踪宏观扩张,c++,macros,boost-preprocessor,C++,Macros,Boost Preprocessor,我想跟踪宏的扩展-宏被扩展了多少次,以及扩展发生时的参数是什么 比如说, #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_INDIR

我想跟踪宏的扩展-宏被扩展了多少次,以及扩展发生时的参数是什么

比如说,

#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)
我有一个宏可能如下所示:

#define mymacro(x) int x
mymacro(a);
mymacro(b);
在我的代码中,我有如下内容:

#define mymacro(x) int x
mymacro(a);
mymacro(b);
在预处理器扩展的最后(哦,是的,有没有办法使一个特定的宏成为最后一个扩展的宏?),我想知道mymacro被使用了多少次,传递了哪些参数。在这种情况下,它将是2倍,args将是a和b

我在研究boost预处理器库。他们有BOOST_PP_数组,但我不知道如何使它“静态”,以便我以后可以使用它


我在BOOST_PP_计数器中发现了一些东西。看起来BOOST_PP_计数器可以在预处理器阶段保持其状态。但我仍然不清楚如何做我想做的事。

像这样的事情怎么样

#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";
    }
}
#包括
int m_计数器=0;
const char*m_参数[32]={0};
#定义COUNT_M(a)M_参数[M_counter++]=#a;
#定义M(a)计数\u M(a)整数a
int main()
{
M(x);
M(y);
对于(int i=0;i像这样的怎么样

#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";
    }
}
#包括
int m_计数器=0;
const char*m_参数[32]={0};
#定义COUNT_M(a)M_参数[M_counter++]=#a;
#定义M(a)计数\u M(a)整数a
int main()
{
M(x);
M(y);
对于(int i=0;istd::cout我不太确定您的最终目标是什么,但您可以使用活动参数跟踪扫描次数(而不是扩展次数)。活动参数每次被预处理器扫描时都会扩展。例如

#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)
对的每次调用都会进行不同数量的扫描,这会导致每次的结果都不同


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

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

#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)
对的每次调用都会进行不同数量的扫描,这会导致每次的结果都不同


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

如果编译器支持,可以通过在宏中添加一行输出编译器消息来实现。您能更具体一点吗?我使用的是ClangIt,我现在还不清楚,但您所说的是对正在发生的事情的检查,并且希望得到结果(即调用它的内容等)在预处理时可用,以便您可以使用它,对吗?是的,这就是我想要做的我希望您不要期望在编译单元之间保持此计数…如果您的编译器支持,可以通过向输出编译器消息的宏添加一行来实现。您能更具体一点吗?我使用的是ClangIt对我来说还不是很清楚,但你说的是过去对正在发生的事情的检查,并希望得到结果(即调用它的内容等…)在预处理时可用,以便您可以使用它,对吗?是的,这就是我想要做的我希望您不要期望在编译单元之间保持此计数…嗯…在本例中为M(x)和M(y)需要在运行时调用才能工作。我的MARCO是回调,所以不一定要被调用。是否要在编译时执行此操作?嗯……在本例中,M(x)和M(y)需要在运行时调用才能工作。我的MARCO是回调,所以不一定要被调用。是否要在编译时执行此操作?