Std::unique_ptr

So I noticed in the Main.cpp that ScopedPointer mainWindow; changed to std::unique_ptr mainWindow; Coming from a C# I have been contented just using new and delete concept as this made sense to me (I have been bitten a few times with the sequencencing when destroying and access violations on threads). Reading the roadmap saying that juce library wants to replace out ScopedPointer in favour of the standard libraries unique_ptr is this the correct way of using in a juce context or is there going to be a different way?

public:
    std::unique_ptr<Header> header;

then used…

addAndMakeVisible( (header = std::make_unique()).get() );

If this object has a default constructor, then why use a pointer at all? Unless you actually need it to be a pointer, just using a member variable is by far the best way of handling object lifetimes.

public:
    Header header;


addAndMakeVisible (header);
2 Likes

Cheers, yeah I usually do that with controls such as knobs, sliders, buttons e.t.c. but I do find it handier to have things like scenes to be pointers as I have an extended component class with a few extra methods for passing info and events between. Just checking that I wasn’t doing anything stupid if I did it that way?

Yeah, it’s fine.

I think it’d read better like this though:

header = std::make_unique<Header>();
addAndMakeVisible (*header);
1 Like

Or you may prefer to do it all on one line

addAndMakeVisible(*(header = std::make_unique<Header>()));,

which is how I ended up doing it when I refactored to remove all the ScopedPointers.

It’s a common use-case. I wonder if it would make sense to add a templated method to Component like this?

template <typename ChildCompType, template... Parameters>
std::unique_ptr<ChildCompType> createChild (Parameters...);

…so you could write


struct ParentComp
{
    ParentComp()
    {
        child = createChild<MyChild> (1234);
    }

    std::unique_ptr<MyChild> child;
6 Likes

I was about to propose adding that. :slight_smile:

I try to use this syntax:

header = std::make_unique<Header>();
addAndMakeVisible( header.get() );

addAndMakeVisible takes references and pointers. imo, the syntax for pointer dereferencing is super ugly, so I avoid it as much as possible, unless absolutely required.

1 Like

Not sure if the juce team as a preference, as both notations

header = std::make_unique<Header>();
addAndMakeVisible (*header);

and

header = std::make_unique<Header>();
addAndMakeVisible (header.get());

are used in the codebase. perhaps it could be made consistent and part of the code style guidelines?
My vote goes for *

Personally I would prefer the addAndMakeVisible (Component&) overload because it’s slightly more efficient but also clearer if you know the object is valid.

Personally I often do:
addAndMakeVisible (*(header = std::make_unique<Header>()))
but I’m aware that’s a little parenthesis heavy.

Jule’s suggestion or even a templated pointer version could work?

template<typename ComponentPointerType>
addAndMakeVisible (ComponentPointerType&& ptr)
{
    if (ptr != nullptr)
        addAndMakeVisible (*ptr);
}

could work…

1 Like