不能在C++构造函数中使用宏

Cannot use Macro in a C++ constructor?

本文关键字:构造函数 C++ 不能      更新时间:2023-10-16

我有一个复杂的类,我试图用宏来简化它。宏在某些编译器中运行良好,但在其他编译器中则不然。我以为宏只是文本替换,我错了吗?

struct FooManager
{
    FooManager(){}
    void Add( Foo* i_pFoo ){ m_FooObjects.Add( i_pFoo ); }
private:
    DynamicArray<Foo*> m_FooObjects;
};
struct Foo
{
   Foo( FooManager& mgr, int param1, int param2 = 0 )
       : m_Param1( param1 )
       , m_Param2( param2 )
   {
       mgr.Add( this );
   }
private:
    const int m_Param1, m_Param2;
}
class Bar
{
    FooManager m_Manager;
    Foo m_Foo1, m_Foo2;
public:
    Bar();
};

然后在.cpp文件中。。。

#define Macro( f, a, ... ) f( m_Manager, a, __VA_ARGS__ )
Bar::Bar()
    : m_Manager()
    , Macro( m_Foo1, 1 )
    , Macro( m_Foo2, 2, 3 )
{}

在使用gcc编译器时,我得到了一个"错误29:应为表达式"。

我真正想要的是我的酒吧有一个了解所有Foo的经理。我可以打开Macro,但希望我不必这样做,因为它让东西看起来更干净,而且它可以根据使用情况提供其他共享参数。

我倾向于相信,我这样做违反了一条规则,而与之合作的编译器出于某种原因忽视了这条规则。

__VA_ARGS__为空的情况下(例如,展开Macro( m_Foo1, 1 )时),宏将在构造函数初始值设定项列表中生成以下条目

m_Manager(<some argument>, )

这显然是无效的。__VA_ARGS__的思想是,您应该为__VA_ARGS__部分提供至少一个参数。

为了使__VA_ARGS__更容易在这种情况下使用,像MSVC这样的编译器在这种情况中会实现非标准行为:它们会悄悄地删除多余的逗号,使您的原始代码能够按预期编译。

GCC还实现了一个非标准扩展,用于相同的目的,但您必须使用## 的非标准技巧来激活它

#define Macro( f, a, ... ) f( m_Manager, a, ##__VA_ARGS__ )

__VA_ARGS__为空时,这将自动删除GCC中的尾随逗号。