Richard
Richard

Reputation: 8758

How to safely downcast USTRUCTs

Unreal Engine supports downcasting of UObject* via Cast<T> and via a custom implementation of dynamic_cast<T*>.

When downcasting USTRUCT objects, both methods don't work:

  1. The methods of Cast<T> do not support conversions to UScriptStructs.
  2. UE4 compiles without RTTI (e.g. /GR- is set for cl.exe) and UE4 uses the dynamic_cast<T*> of the implementation for pointers to USTRUCTs. Therefore the compiler throws C4541 (see example below).

Is there a method in UE4.22 to safely downcast USTRUCTs using the reflection system of UE4 (so when static_cast<T*> etc is not an option)?

If not, then why UE4 doesn't support downcasting USTRUCTs by its Cast functions? E.g. shouldn't they be referenced or are the reasons Blueprint related?


Example for (2), use within an UE4 project:

#pragma once
#include "CoreMinimal.h"

USTRUCT()
struct MyStructBase
{
    virtual ~MyStructBase() = default;
};

USTRUCT()
struct MyStructDerived : public MyStructBase
{};

void TestFunc()
{
    auto lvalue = MyStructBase{};
    auto lvaluePtr = &lvalue;
    auto o = dynamic_cast<MyStructDerived*>(lvaluePtr); // cl.exe throws C4541
}

Upvotes: 3

Views: 8232

Answers (3)

user17509487
user17509487

Reputation: 1

You can also check the safety of a structure cast by checking if the type of the structure is a child of the type you're casting to, and the type you're casting to is a child of the structure type. If both conditions are true they're the same type.

Upvotes: 0

Vennor
Vennor

Reputation: 656

Is there a method in UE4.22 to safely downcast USTRUCTs using the reflection system of UE4 (so when static_cast<T*> etc is not an option)?

I know it's not an ideal solution and might not suit your case, but if you don't want to use a bare static_cast, you could provide a templated function that does the cast and add a static_assert with TIsDerivedFrom inside to get a compile time error were the cast to fail.

template<typename T, typename U>
T* CastStruct(U* base)
{
    static_assert(TIsDerivedFrom<T, U>::IsDerived, "Type T has to be derived from U.");
    return static_cast<T*>(base);
}

why UE4 doesn't support downcasting USTRUCTs by its Cast functions?

That's because structures are supposed to be lightweight entities in Unreal Engine and thus reflection - which is required for Cast to work - is not provided provided in a minimal form for them.

Be careful when using pointers to USTRUCTs as they're not only unsupported by reflection, but also garbage collector, serializers, UI etc. You have to know what you're doing when dealing with them.

Upvotes: 3

Chris Gong
Chris Gong

Reputation: 8229

According to this post in the Unreal forums, there is no working dynamic cast for UStruct in Unreal. I'm not sure why, but it seems that pointers to objects of type UStruct are not support by Unreal's reflection system, according to this post.

Your options here include a C-style cast and like you mentioned, a static cast. However, either option isn't that safe, with the exception that static casts are usually safe when you know the object being passed to the cast is of the type specified in the cast.

C-style cast:

auto o = (MyStructDerived*) lvaluePtr;

Static cast:

auto o = static_cast<MyStructDerived*>(lvaluePtr);

Upvotes: 0

Related Questions