Nested class constructor

Howdy!
Native programing is more nasty than I thought. So I came across the nested class definition (in SScissorRectBox.h)


class SLATE_API SScissorRectBox : public SPanel
{

public:
    class FScissorRectSlot : public TSupportsOneChildMixin<FScissorRectSlot>
    {
    public:
        FScissorRectSlot(SWidget* InOwner)
            : TSupportsOneChildMixin<FScissorRectSlot>(InOwner)
        {}
    };

    SLATE_BEGIN_ARGS(SScissorRectBox)
    {
        _Visibility = EVisibility::SelfHitTestInvisible;
        _Clipping = EWidgetClipping::ClipToBounds;
    }
        SLATE_DEFAULT_SLOT(FArguments, Content)
    SLATE_END_ARGS()

    void Construct( const FArguments& InArgs );

    /**
     * See the Content slot.
     */
    void SetContent(const TSharedRef< SWidget >& InContent);

private:
    virtual FVector2D ComputeDesiredSize(float) const override;
    virtual void OnArrangeChildren( const FGeometry& AllottedGeometry, FArrangedChildren& ArrangedChildren ) const override;
    virtual FChildren* GetChildren() override;
    virtual int32 OnPaint( const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyCullingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled ) const override;

    FScissorRectSlot ChildSlot;
};

for which the object declaration in the following fashion


TSharedPtr<SScissorRectBox> ScissorRectBox = SNew(SScissorRectBox)[RebuildListWidget()];



where RebuildListWidget() is declared as


virtual TSharedRef<SListView<UObject*>> RebuildListWidget();

yields the error


default constructor of 'SScissorRectBox' is implicitly deleted because field 'ChildSlot' has no default constructor

FScissorRectSlot ChildSlot;


Now it makes me think that the additional lines


class FScissorRectSlot : public TSupportsOneChildMixin<FScissorRectSlot>
    {
    public:
        FScissorRectSlot(SWidget* InOwner)
            : TSupportsOneChildMixin<FScissorRectSlot>(InOwner)
        {}
       FScissorRectSlot()
       {}
    };

should rectify the error. I haven’t compiled the code because it means changing the Engine code. Just looking for the second opinion :smiley:

Simplest way is just add default value (of course if implementation provide support for handling nullptr as owner, but anyway pointer initialized with nullptr is always better than non-initialized pointer)


FScissorRectSlot(SWidget* InOwner = nullptr)

Cool, I will try that and report how it goes. Thanks!

Edit:
Oops, didn’t see the data type in hurry. Do you mean to replace the



TSharedPtr<SScissorRectBox> ScissorRectBox = SNew(SScissorRectBox)[RebuildListWidget()];


with



FScissorRectSlot(SWidget* InOwner = nullptr)


?

So, I could not resolve the error. Perhaps, I should report the error with different angle. Right now I am using the following declaration


TSharedPtr<SScissorRectBox> ScissorRectBox = SNew(SScissorRectBox)[SScissorRectBox::FScissorRectSlot(nullptr), RebuildListWidget()];

with the hope that the nested class FScissorRectSlot will pick the nullptr for constructor purpose (I am assuming anything in the square brackets means arguments for SNew method).

The sequence/cluster of errors spit is



/home/the_cowboy/unrealworks/UnrealEngine/Engine/Source/Runtime/Core/Public/Templates/SharedPointerInternals.h:135:32: error: call to implicitly-deleted default constructor of 'SScissorRectBox'

new ((void*)&ObjectStorage) ObjectType(Forward<ArgTypes>(Args)...);

^

/home/the_cowboy/unrealworks/UnrealEngine/Engine/Source/Runtime/Core/Public/Templates/SharedPointerInternals.h:186:14: note: in instantiation of function template specialization 'SharedPointerInternals::TIntrusiveReferenceController<SScissorRectBox>::TIntrusiveReferenceController<>' requested here

return new TIntrusiveReferenceController<ObjectType>(Forward<ArgTypes>(Args)...);

^

/home/the_cowboy/unrealworks/UnrealEngine/Engine/Source/Runtime/Core/Public/Templates/SharedPointer.h:1692:108: note: in instantiation of function template specialization 'SharedPointerInternals::NewIntrusiveReferenceController<SScissorRectBox>' requested here

SharedPointerInternals::TIntrusiveReferenceController<InObjectType>* Controller = SharedPointerInternals::NewIntrusiveReferenceController<InObjectType>(Forward<InArgTypes>(Args)...);

^

/home/the_cowboy/unrealworks/UnrealEngine/Engine/Source/Runtime/SlateCore/Public/Widgets/DeclarativeSyntaxSupport.h:1001:10: note: in instantiation of function template specialization 'MakeShared<SScissorRectBox, ESPMode::NotThreadSafe>' requested here

return MakeShared<WidgetType>();

^

/home/the_cowboy/unrealworks/UnrealEngine/Engine/Source/Runtime/SlateCore/Public/Widgets/DeclarativeSyntaxSupport.h:1034:97: note: in instantiation of member function 'TWidgetAllocator<SScissorRectBox, false>::PrivateAllocateWidget' requested here

: _Widget( TWidgetAllocator<WidgetType, TIsDerivedFrom<WidgetType, SUserWidget>::IsDerived >::PrivateAllocateWidget() )

^

/home/the_cowboy/unrealworks/UnrealEngine/Engine/Source/Runtime/SlateCore/Public/Widgets/DeclarativeSyntaxSupport.h:1111:9: note: in instantiation of member function 'TDecl<SScissorRectBox, RequiredArgs::T0RequiredArgs>::TDecl' requested here

return TDecl<WidgetType, RequiredArgsPayloadType>(InType, InFile, OnLine, Forward<RequiredArgsPayloadType>(InRequiredArgs));

^

/home/the_cowboy/unrealworks/UnrealProjects/UnrealTournament/Source/UnrealTournament/Public/UMG/UTListView.cpp:48:50: note: in instantiation of function template specialization 'MakeTDecl<SScissorRectBox, RequiredArgs::T0RequiredArgs>' requested here

TSharedPtr<SScissorRectBox> ScissorRectBox = SNew(SScissorRectBox)[SScissorRectBox::FScissorRectSlot(nullptr), RebuildListWidget()];

^

/home/the_cowboy/unrealworks/UnrealEngine/Engine/Source/Runtime/SlateCore/Public/Widgets/DeclarativeSyntaxSupport.h:33:2: note: expanded from macro 'SNew'

MakeTDecl<WidgetType>( #WidgetType, __FILE__, __LINE__, RequiredArgs::MakeRequiredArgs(__VA_ARGS__) ) <<= TYPENAME_OUTSIDE_TEMPLATE WidgetType::FArguments()

^

/home/the_cowboy/unrealworks/UnrealEngine/Engine/Source/Runtime/Slate/Public/Widgets/Layout/SScissorRectBox.h:63:19: note: default constructor of 'SScissorRectBox' is implicitly deleted because field 'ChildSlot' has no default constructor

FScissorRectSlot ChildSlot;



Since we are on that, I was wondering if I can get the “parsing” of the method definition (in DeclarativeSupportSyntax.h)


/**
 * Slate widgets are constructed through SNew and SAssignNew.
 * e.g.
 *      
 *     TSharedRef<SButton> MyButton = SNew(SButton);
 *        or
 *     TSharedPtr<SButton> MyButton;
 *     SAssignNew( MyButton, SButton );
 *
 * Using SNew and SAssignNew ensures that widgets are populated
 */

#define SNew( WidgetType, ... ) \
    MakeTDecl<WidgetType>( #WidgetType, __FILE__, __LINE__, RequiredArgs::MakeRequiredArgs(__VA_ARGS__) ) <<= TYPENAME_OUTSIDE_TEMPLATE WidgetType::FArguments()



Especially what do ‘’, ‘<<==’ refer to here?

\ at end of line means the define continues into the next line

Cool, thanks. But why new line is needed. Is it a text aesthetics thingy (if true it certainly beats the purpose).

Bump! It’d be really a learning step for me if I get the right interpretation of the code in post #4. Especially what do the square brackets ] represent. Another live example is at https://github.com/EpicGames/UnrealT…idgetFactory.h line 180.

The \ will be always used to tell the compiler that what comes next should be handled as if it will continue in the same line. The purpose is just to make the text clear and it can be used for macros (#define) and also to tell that a string should me merged if used like:

… “string x”
“still string x”

Those brackets without looking at the code tells me the operator] is overloaded, then we should look at the definition for the overload operation and analyse whats happening there. I just passed by this thread, just giving the hint, not sure I will handle some time to look at.

You should be able to do this:



    TSharedRef<SBox> MyBox = SNew(SBox);

    TSharedPtr<SScissorRectBox> ScissorRectBox = SNew(SScissorRectBox)
    .Content()
    
        MyBox
    ];


However to me seems like that “SScissorRectBox” class is incomplete.
The Construct() function should deal with this stuff by itself since “FScissorRectSlot” constructor won’t get called by SScissorRectBox’s default.

Thanks Lima and XaVIeR for the helpful posts. The “SScissorRectBox” is indeed incomplete, I might probably open a pull request (I am not positive because Epic didn’t accept my last request, but hey, world is based on hope).

Don’t stop contributing just because the last thing wasn’t accepted. :smiley:

Done https://github.com/EpicGames/UnrealEngine/pull/5989

The slot has to be passed a valid parent the issue is a missing constructor in SScissorRectBox:
SScissorRectBox::SScissorRectBox() :ChildSlot(this) {}
I’ve added this in CL 7282470 it will be in 4.24

In the PR discussion there were also question about it wrt to dealing directly with slots.
This just isn’t the way Slate intends you to work with slots it’s implementation attempts to keep protect the user from some details here.