Reducing code bloat of pointer / IsValid checks?

Roy Wierer (Seda145)
Thu, 23 Mar 2023 03:43:35 +0000
C++

I mostly separate the UI design proces from the programming by binding optional widgets from the blueprint designer to a pointer in c++. If you are not familiar with such pointer property, it looks like this:

UPROPERTY(meta = (BindWidgetOptional))
UMyWidget* MyWidget = nullptr;

This works very well except that if you bind a ton of widgets this way, you end up with a ton of pointers. Meaning you have to constantly check the pointers before accessing your widget data.

The normal way:

if (IsValid(A)) {
	A->SetVisibility(NewVisibility);
}
if (IsValid(B)) {
	B->SetVisibility(NewVisibility);
}
if (IsValid(C)) {
	C->SetVisibility(NewVisibility);
}
if (IsValid(D)) {
	D->SetVisibility(NewVisibility);
}

The typing less way:

auto TrySetVisibility = [&NewVisibility] (UWidget* InWidget) {
  if (IsValid(InWidget)) {
    InWidget->SetVisibility(NewVisibility);
  }
};

TrySetVisibility (A);
TrySetVisibility (B);
TrySetVisibility (C);
TrySetVisibility (D);

// Doing it in a loop would require you to actually know what panel they are on, or add an array of widgets, which is out of the question.

Not a big deal, unless you are working with an amount of widgets this is going to cost too much time or were a copy pasta mistake is likely.

Getting creative…

  UObject* A = nullptr;
  UObject* B = nullptr;
  UObject* C = nullptr;

  auto Test = [](UObject& InObject) -> bool {
      // dostuff
      return true;
  };

  auto DoIfValid = [](UObject* InObject, auto&& InFunc) {
      if (IsValid(InObject)) {
          return InFunc(*InObject);
      }
  };

  bool X = DoIfValid(A, Test);
  DoIfValid(B, Test);
  DoIfValid(C, Test);

Lambdas… Templates… What is your recommended way in 2023?

1 post - 1 participant