Actually, using a struct with state is identical to using a lambda with a capture. A lambda is not like a function pointer, though capture-less lambdas are convertible to function pointers.
The FSortByDistance code above is equivalent to the following with a lambda:
FVector SourceLocation = ControlledMob->GetActorLocation();
GetSensedActors().Sort([SourceLocation](const AActor& A, const AActor& B)
{
float DistanceA = FVector::DistSquared(SourceLocation, A.GetActorLocation());
float DistanceB = FVector::DistSquared(SourceLocation, B.GetActorLocation());
return DistanceA > DistanceB;
});
But while lambdas are more than capable of expressing stateful predicates, you may still want to define a standalone FSortByDistance struct to allow code reuse.
However, note that I have changed the code above to pass AActor by reference instead of by pointer. This is due to a legacy decision that causes TArray::Sort() to auto-deference pointers, and will have been the reason for your compile errors. Unfortunately, we can’t realistically revert that behaviour now, so instead, you should prefer to use Algo::Sort over TArray::Sort, as this correctly passes pointers to the predicate as expected:
struct FSortByDistance
{
explicit FSortByDistance(const FVector& InSourceLocation)
: SourceLocation(InSourceLocation)
{
}
/* The Location to use in our Sort comparison. */
FVector SourceLocation;
bool operator()(const AActor* A, const AActor* B) const
{
float DistanceA = FVector::DistSquared(SourceLocation, A->GetActorLocation());
float DistanceB = FVector::DistSquared(SourceLocation, B->GetActorLocation());
return DistanceA > DistanceB;
}
};
Algo::Sort(GetSensedActors(), FSortByDistance(ControlledMob->GetActorLocation()));
Hope this helps,
Steve