Casting slate widgets

Hi!

This is probably a simple question:
How do i cast from SWidget to STextBlock?

I tried for some hours now. So far nothing works.
Here are some things i have already tried:

STextBlock textBlock = (STextBlock)this->ContentSlot->GetWidget().Get();
//Error C2440 : 'type cast' : cannot convert from 'SWidget' to 'STextBlock'

STextBlock textBlock = dynamic_cast<STextBlock>(this->ContentSlot->GetWidget().Get());
//Error C2680: 'STextBlock' : invalid target type for dynamic_cast

I feel its something simple and obvious, but i could use someone to point it out to me :slight_smile:

You’re trying to cast to a value type, which means you’re telling the compiler to try to construct a new object from the result of Get(). Your first line is equivalent to using static_cast, but still all that means is constructing an STextBlock from an SWidget, instead of casting it.

What you want to do is cast the reference, like so:

static_cast< STextBlock& >(this->ContentSlot->GetWidget().Get())

This way, you’re not copying the object, you’re casting a reference to it. The choice between static_cast and dynamic_cast is yours, although dynamic_cast can only be used with a pointer, since references are not nullable:

dynamic_cast< STextBlock* >(&this->ContentSlot->GetWidget().Get())

More excellent reading on the subject here.

Using dynamic_cast gives me this error: C4541: ‘dynamic_cast’ used on polymorphic type ‘SWidget’ with /GR-; unpredictable behavior may result

I will have to read on that.

Your static_cast solution works fine. So, thanks for your help :slight_smile:
Coming from C# (Not Unity, but business application dev) all that casting, pointer and reference stuff is mysterious.
The good thing with UE4 is that i finally have a reason to learn c++

Ah yes, in Unreal you would just use Cast<> instead of dynamic_cast<>, as by default Unreal disables an option on the compiler that prevents usage of the native dynamic_cast. However, Cast<> only works on UObjects, so with your SWidgets you’ll be limited to static_cast, which will yield undefined behavior if the thing you’re casting is not actually of the type you’re looking for.

To protect against the undefined behavior of static_cast you can do a check like this:

TSharedPtr<SWidget> widget;
if (widget->GetType() == "SObjectWidget")
{
    SObjectWidget* objectWidget = static_cast<SObjectWidget*>(widget.Get());
}
4 Likes

Thank u guys, this post solved all of my problems.

You can use StaticCastSharedPtr

3 Likes

I think likw static_cast, StaticCastSharedPtr does not do anything to check the type so still needs if (widget->GetType() == "typename") before if you don’t know for sure it is safe to downcast.

Is there any utility function that casts it and checks the type, setting the TSharedPtr to null/Invalid on fail? I think GetType gives an FName, so it is maybe not possible without a macro, or C++ reflection whenever that gets added?

1 Like