不能在 C++ 构造函数中使用宏?
Cannot use Macro in a C++ constructor?
我有一个复杂的 class,我试图用宏来简化它。该宏适用于某些编译器,但不适用于其他编译器。我以为宏只是文本替换,我错了吗?
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 编译器时得到一个 "error 29: expected an expression"。
我真正想要的是我的 Bar 有一个了解其中所有 Foo 的经理。我可以展开宏,但希望我不必这样做,因为它让事情看起来更清晰,并且它可以根据使用情况提供其他共享参数。
我倾向于认为我这样做违反了一条规则,并且与之一起工作的编译器出于某种原因忽略了这条规则。
在 __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 中的尾随逗号。
我有一个复杂的 class,我试图用宏来简化它。该宏适用于某些编译器,但不适用于其他编译器。我以为宏只是文本替换,我错了吗?
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 编译器时得到一个 "error 29: expected an expression"。
我真正想要的是我的 Bar 有一个了解其中所有 Foo 的经理。我可以展开宏,但希望我不必这样做,因为它让事情看起来更清晰,并且它可以根据使用情况提供其他共享参数。
我倾向于认为我这样做违反了一条规则,并且与之一起工作的编译器出于某种原因忽略了这条规则。
在 __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 中的尾随逗号。