Hey, I’m just adding the actors from a sphere trace to an array and then attempting to sort them by distance to the AI. This is my first time using the Sort() function and i swear this compiled previously.
TArray<AActor*> TargetActors;
FVector Location = TreeComp.GetAIOwner()->GetPawn()->GetActorLocation();
TargetActors.Sort([Location](const AActor* A, const AActor* B)
{
return FVector::DistSquared(Location, A->GetActorLocation()) < FVector::DistSquared(Location, B->GetActorLocation());
});
Visual Studios says No Issues Found but there’s a bunch of errors when compiling.
Hey, using an actor reference instead of a pointer worked for this. I’m guessing this is the most important error that i missed “”<lambda_2>>(const PREDICATE_CLASS &)’ “”
But i posted the rest of the errors if there’s something to learn from it.
error C2664: 'bool UBTTFindTarget::ExecuteTask::<lambda_2>::operator ()(const AActor *,const AActor *) const': cannot convert argument 1 from 'T' to 'const AActor *'
2> with
2> [
2> T=AActor
2> ]
Sorting.h(38): note: No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
note: see declaration of 'UBTTFindTarget::ExecuteTask::<lambda_2>::operator ()'
Sorting.h(38): note: while trying to match the argument list '(T, T)'
2> with
2> [
2> T=AActor
2> ]
Sorting.h(38): note: the template instantiation context (the oldest one first) is
note: see reference to function template instantiation 'void TArray<AActor *,TSizedDefaultAllocator<32>>::Sort<UBTTFindTarget::ExecuteTask::<lambda_2>>(const PREDICATE_CLASS &)' being compiled
2> with
2> [
2> PREDICATE_CLASS=UBTTFindTarget::ExecuteTask::<lambda_2>
2> ]
note: see the first reference to 'TArray<AActor *,TSizedDefaultAllocator<32>>::Sort' in 'UBTTFindTarget::ExecuteTask'
Array.h(3007): note: see reference to class template instantiation 'TDereferenceWrapper<AActor *,PREDICATE_CLASS>' being compiled
2> with
2> [
2> PREDICATE_CLASS=UBTTFindTarget::ExecuteTask::<lambda_2>
2> ]
Sorting.h(36): note: while compiling class template member function 'bool TDereferenceWrapper<AActor *,PREDICATE_CLASS>::operator ()(T *,T *) const'
2> with
2> [
2> PREDICATE_CLASS=UBTTFindTarget::ExecuteTask::<lambda_2>,
2> T=AActor
2> ]
Invoke.h(47): note: see the first reference to 'TDereferenceWrapper<AActor *,PREDICATE_CLASS>::operator ()' in 'Invoke'
2> with
2> [
2> PREDICATE_CLASS=UBTTFindTarget::ExecuteTask::<lambda_2>
2> ]
Amazing, thank you!
I mostly use pointers because I’ve seen so many “value must be modifiable lvalue” errors.
But a const pointer doesn’t make sense now that I’m thinking about it.
If you don’t mind I have a few questions.
Do Lambda functions just require a const reference or is there more going on?
What are some instances to use a reference instead of a pointer assuming there is an advantage?
This is more about how unreal handles predicate. UE’s sort system auto-dereferences pointer elements before comparing them, so your predicate must take references (AActor&), not pointers (AActor*).
Yeah, it’s dumb that the errors don’t really call this issue out.
As KaidoomDev points out it’s specific to Unreal and the TArray. There’s a comment on the sorting functions that say this is the behavior (for whatever reason) to expect with TArrays of raw pointers.
One isn’t necessarily better than the other. In theory (in another codebase) you might use references as a way to self-document that the parameter can’t be nullptr. But Epic is inconsistent in this regard. Some places do this, others don’t. I’ve never thought this is particularly safe since there could be nulls in the array and it’s unclear how it handles those to not crash.