This, will not compile
for (AActor* actor : overlappedItems)
{
AWorldItem* item = StaticCast<AWorldItem *, AActor *>(actor);
}
I have used StaticCast elsewhere in my code, and I am failing to see how this is different?
Here is a working example:
AWorldItem* item = StaticCast<AWorldItem*, UObject*>(grabbedItem.GetObject());
And another:
OnSequenceEnded.Broadcast(StaticCast<ULevelSequence *, UMovieSceneSequence *>(MovieActor->SequencePlayer->GetSequence()));
I am failing to see how these differ, as these functions just return pointers to these values, the same as the matching ArgType which is specified.
I’m not the most experienced with C, so I’m sorry if this is a super simple question.
Presumably either AWorldItem
is not an AActor
, or the compiler doesn’t know it’s one at this point (have you #include
d the header for AWorldItem
?)
FYI you don’t need to provide the second template argument to StaticCast
, it can be deduced.
You should probably be using Cast
instead, which will return null
if the actor isn’t actually an AWorldItem
.
I have included the WorldItem.h file, I’m using it elsewhere in the code so it does know what it is, and it is an AActor.
The main reason I wanted to use static cast is because I know that these are all AWorldItems, the reason I know is because the way this list is being populated, is I am using a ClassFilter of AWorldItem::StaticClass();
here is the code in full context.
TArray<AActor*> overlappedItems;
boxCol->GetOverlappingActors(overlappedItems, AWorldItem::StaticClass());
for (AActor* actor : overlappedItems)
{
AWorldItem* item = StaticCast<AWorldItem *, AActor *>(actor);
item->itemBoundsOverlaps++;
}
This is the StaticCast that does not compile.
As mentioned though, if I sub this out with AWorldItem* item = Cast<AWorldItem>(actor);
it compiles fine.
StaticCast has a specific use case, it’s not meant to be exchanged with Cast just anywhere you want.
It’s not the cast that fails but rather the fact that your looping variable (AActor* actor) cannot be used as an rvalue-reference (&& argument).
This is far from being a simple question, you can look up articles on && function arguments or c++11 rvalue references. StackOverflow
Aside from that, I’m not sure what your reason is for using StaticCast instead of Cast ???
If you KNOW all your items are AWorldItem and your goal is to reduce overhead, use good old C style casting instead :
AWorldItem* item = (AWorldItem*)actor;
5 Likes
Awesome! This is super helpful information, thanks so much!
Yeah the goal was to reduce overhead. I didn’t want to use the classic C-Style cast, as it was my understanding that there were occasional complications that Unreal ran into when using this style cast. But that may not be the case, I don’t remember where I learned that or if it was accurate.
Thanks for the help!
Well I’ve learned something here, too!
If you know for sure that the cast will succeed, you can use the normal C++ static_cast<AWorldItem*>(actor);
- I do this in my code, my mistake was assuming StaticCast
was just an alias. You can’t use dynamic_cast
, which Cast
is an Unreal-specific replacement for.
Reason to avoid C-style casting is the same as in any C++ codebase: the modern C++ casts provide more restrictions than C-style casting to help stop you making weird mistakes, like casting away constness or reinterpreting to an unrelated type.
I try to avoid static_cast
and use Cast whenever I can for consistency (So on all UObjects). static_cast is used once or twice when working with the old Slate code but leads to ugly code and undefined behavior if the thing you are casting is not exactly what you are casting to.
In all our game code we use the standard Unreal Cast:
T* ptr = Cast<T>(object)
Writeup on why here:
Peter Leontev - Entrepreneur & Game Tools & Tech Programmer | How Unreal Engine C++ Cast function works?
AFAIK there is no reason to use anything but Cast except special cases or not using standard UObjects.