首页 > 解决方案 > C ++如何有条件地调用全局函数,无论是否在静态方法中?

问题描述

我将以我对合理的替代方案持开放态度这一事实作为这个问题的开头,这就是我们目前陷入困境的地方。

我们希望在我们的游戏引擎中有一个 Assert() 宏,如果从 GameObject 方法中调用,它能够自动记录有关基本 GameObjects 的元数据。询问 SO 的动机是,我们目前受困于两个断言变体:Assert() 和 AssertInStatic(),但更喜欢只有一个。

代码问题(注意:不是确切的代码,但概述了问题):

// macro
#define Assert(expr, msg) \
    if (!(expr)) DoAssert(msg, __FILE__, __LINE__)
#define AssertInStatic(expr, msg) \
    if (!(expr)) ::DoAssert(msg, __FILE__, __LINE__)

// global function
bool DoAssert(msg, file, line);

class GameObject {
    protected:
        // game object assert method
        bool DoAssert(msg, file, line); // logs extra object metadata
};

// any global function or non-GameObject method
void foo()
{
    Assert(condition, "msg"); // calls global assert function
}

// regular GameObject method
void GameObject::foo()
{
    Assert(condition, "msg"); // calls GameObject assert method
}

// STATIC GameObject method
/*static*/ void GameObject::static_foo()
{
    //Assert(condition, "msg"); // <ERROR: class assert method uncallable, hides global function>
    AssertInStatic(condition, "msg"); // works, calls global assert, but would rather not have this special case
}

我们找到的最接近的解决方案在 MSVC 上是这样的(但我们也需要该解决方案可以在 clang 和 gcc 之间移植):

// msvc:
__if_exists(this) {
    DoAssert(...);
}
__if_not_exists(this) {
    ::DoAssert(...);
}

标签: c++

解决方案


您可以考虑使用可变参数宏来重载带有可选参数的宏名称。因此参数的数量将区分全局和对象断言。它可能是一个虚拟参数或特定于对象的东西。

请参阅C++ 宏的可选参数


推荐阅读