I found my self constantly checking many objects to see if they are valid so I started using these two macros in my code. [FONT=Courier New]AllValid(…) and [FONT=Courier New]AnyInvalid(…). Essentially I turned all statements like this:
if(IsValid(Obj) && IsValid(OtherObj)) {
Obj->DoThing();
OtherObj->DoOtherThings(Obj);
}
To something like this:
if(AllValid(Obj, OtherObj)) {
Obj->DoThing();
OtherObj->DoOtherThings(Obj);
}
You could also do this at the top of a function if it requires certain objects to be valid.
if(AnyInvalid(Obj1, Obj2, Obj3)) {
return;
}
The valid checking is done in sequential order so you can use the previous object in the next argument.
UWorld* world;
if(AnyInvalid(SomeActor, world = SomeActor->GetWorld())) {
return;
}
Here’s the source:
#define EXPAND(x) x
#define CAT( A, B ) A ## B
#define SELECT( NAME, NUM ) CAT( NAME ## _, NUM )
#define GET_COUNT( _1, _2, _3, _4, _5, _6, COUNT, ... ) COUNT
#define VA_SIZE( ... ) EXPAND(GET_COUNT( __VA_ARGS__, 6, 5, 4, 3, 2, 1 ))
#define VA_SELECT( NAME, ... ) EXPAND(SELECT( NAME, VA_SIZE(__VA_ARGS__) )(__VA_ARGS__))
#define AllValid( ... ) (VA_SELECT( AllValidArg, __VA_ARGS__ ))
#define AllValidArg_1(_obj1) IsValid(_obj1)
#define AllValidArg_2(_obj1, _obj2) AllValidArg_1(_obj1) && IsValid(_obj2)
#define AllValidArg_3(_obj1, _obj2, _obj3) AllValidArg_2(_obj1, _obj2) && IsValid(_obj3)
#define AllValidArg_4(_obj1, _obj2, _obj3, _obj4) AllValidArg_3(_obj1, _obj2, _obj3) && IsValid(_obj4)
#define AllValidArg_5(_obj1, _obj2, _obj3, _obj4, _obj5) AllValidArg_4(_obj1, _obj2, _obj3, _obj4) && IsValid(_obj5)
#define AllValidArg_6(_obj1, _obj2, _obj3, _obj4, _obj5, _obj6) AllValidArg_5(_obj1, _obj2, _obj3, _obj4, _obj5) && IsValid(_obj6)
#define AnyInvalid( ... ) (VA_SELECT( AnyInvalidArg, __VA_ARGS__ ))
#define AnyInvalidArg_1( _obj1 ) !IsValid(_obj1)
#define AnyInvalidArg_2( _obj1, _obj2 ) AnyInvalidArg_1(_obj1) || !IsValid(_obj2)
#define AnyInvalidArg_3(_obj1, _obj2, _obj3) AnyInvalidArg_2(_obj1, _obj2) || !IsValid(_obj3)
#define AnyInvalidArg_4(_obj1, _obj2, _obj3, _obj4) AnyInvalidArg_3(_obj1, _obj2, _obj3) || !IsValid(_obj4)
#define AnyInvalidArg_5(_obj1, _obj2, _obj3, _obj4, _obj5) AnyInvalidArg_4(_obj1, _obj2, _obj3, _obj4) || !IsValid(_obj5)
#define AnyInvalidArg_6(_obj1, _obj2, _obj3, _obj4, _obj5, _obj6) AnyInvalidArg_5(_obj1, _obj2, _obj3, _obj4, _obj5) || !IsValid(_obj6)
As you’ve probably noticed it only supports up to 6 arguments, but I’m sure if you need more you could easily add additional arguments if you’d like.
I believe once c++ fold expressions are more widely spread these could be turned into functions.
Another note: the EXPAND macro is used to fix an issue with msvc. It should be unneeded with a properly compliant compiler. (I haven’t tested this on anything else other than msvc)