A macro is just a dumb text replacement that happens before compilation happens. It would only cause a crash if the expanded code would crash.
They’re best avoid precisely because they’re just a dumb text replacement. You can’t debug them, the compiler can’t tell you if you messed up as it will only see what the macro expanded to, etc.
I suggest you read the answer for this SO post
c++ - Why are preprocessor macros evil and what are the alternatives? - Stack Overflow
Well if you have a base class that has SetupWidget then you can just use that base class and make it a normal function
UUMGBase* Foo::Setup(TSubclassOf<UUMGBase> StoreUIClass)
{
UUMGBase* StoreUI = CreateWidget<UUMGBase>(GetWorld(), StoreUIClass);
if (StoreUI)
StoreUI->SetupWidget();
return StoreUI;
}
void Foo::Bar()
{
UUMGBase* Thing = Setup(UIClass);
if (Thing)
{
//use Thing
}
}
Edit: Oh and you can do what the engine does and provide a template version that calls the other i.e. if you need a derived type you would do
UDerivedUMG* Thing = Cast<UDerivedUMG>(Setup(UIClass));
if (Thing)
{
// use Thing
}
which is too much typing for our delicate hands. If you create a template that does
template<class T>
T* Setup(Blah)
{
return Cast<T>(Setup(Blah));
}
You can then just write
UDerivedUMG* Thing = Setup<UDerivedUMG>(UIClass);
if (Thing)
{
// use Thing
}
So this would just be syntactic sugar for C++ code. The first should still work for BP. This is actually what the templated versions of GetController
, GetPawn
, GetOwner
et al. do