3

I will preface this question with the fact that I'm open to reasonable alternatives, this is where we are currently stuck.

We would like to have an Assert() macro in our game engine that is able to automatically log metadata about base GameObjects if called from within a GameObject method. The motivation for asking on SO, is we are currently stuck with two assert variants: Assert() and AssertInStatic(), but would prefer just one.

The code problem (note: not exact code, but outlines the problem):

// 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
}

The closest solution we've come to is something like this on MSVC (but we need the solution to be portable across clang and gcc as well):

// msvc:
__if_exists(this) {
    DoAssert(...);
}
__if_not_exists(this) {
    ::DoAssert(...);
}
Brad Fix
  • 31
  • 5

2 Answers2

1

It’s not pretty, but you can put the static member functions into a base class that lacks the DoAssert member.

Davis Herring
  • 36,443
  • 4
  • 48
  • 76
  • Interesting idea! Unfortunately, there are many child classes of the base game object in the engine that may or may not have static methods. – Brad Fix Nov 04 '20 at 23:38
1

You could consider using variadic macros to overload the macro name with optional parameters. So the number of parameters would distinguish between the global and object assert. It could be a dummy parameter or something specific to the object.

See Optional Parameters with C++ Macros.

ap-osd
  • 2,624
  • 16
  • 16
  • I've considered requiring the user pass in the 'this' pointer to get object metadata logged, which would get around the issue. The ultimate goal was to avoid the user/coder having to do anything explicit and it would just work. – Brad Fix Nov 24 '20 at 22:10