SliderAttachment std::unique_ptr reset does not delete


#1

In our plugin we need to dynamically change SliderAttachments.

Per the documentation, the recommended strategy for SliderAttachments is:

std::unique_ptr<SliderAttachment> sa;
sa.reset (new SliderAttachment (args));
// etc.

This was our initial strategy, with further calls to sa.reset (new SliderAttachment (args)) whenever we needed to change the attachment.

This behaves as expected on the first reassignment, but from that point on it’s as if the second attachment was never replaced at all. The slider displays all the signs of being still linked to the second attachment.

Here are some strategies that *do work for our purposes:

(1)

std::unique_ptr<SliderAttachment> sa;
sa.reset (new SliderAttachment (args));
sa.reset();
sa.reset (new SliderAttachment (args));
// etc.

(2)

SliderAttachment* sa;
sa = new SliderAttachment (args);
delete sa;
sa = new SliderAttachment (args);
// etc.

Have we totally misunderstood the delete behaviour of std::unique_ptrs? Thank you!


#2

Calling reset on a std::unique_ptr will let it point to the new object you are supplying as argument (or nullptr, if none is given), which will result in deleting the object, it was pointing to before.
If you have the std::unique_ptr in a function scope, it will delete whatever it points to, when the function goes out of scope.

Can you post the code, where the std::unique_ptr<SliderAttachment> sa; is located?
Is it a class member or declared inside a method?


#3

Thanks Daniel, sure thing - this is the basic structure

MySlider.h:

class MySlider : public Slider
{
private:
    std::unique_ptr<SliderAttachment> sa;
};

MySlider.cpp:

void MySlider::MySlider()
{
    configureAttachment();
}

void MySlider::handleEvent()
{
    configureAttachment();
}

void MySlider::configureAttachment()
{
    // Set up some temporary variables
    sa.reset (new SliderAttachment (vtsToAttachTo, parameterID, *this));
}

#4

One further bit of clarification:

This behaves as expected on the first reassignment, but from that point on it’s as if the second attachment was never replaced at all. The slider displays all the signs of being still linked to the second attachment.

What I mean in general terms is: The slider behaves as if it is linked to the most novel attachment, ie the one that was most recently created provided that an identical attachment had not previously been created.


#5

Maybe I don’t understand it correctly, but that’s expected, isn’t it? Any new SliderAttachment replaces the previous one.

But on a separate note, I would avoid inheriting Slider for that purpose, but rather having it alongside the slider in the containing Component (or Editor).
Or put it in a struct:

struct AttachedSlider
{
    Slider slider;
    std::unique_ptr<AudioProcessorValueTreeState::SliderAttachment> attachment;
};

Or if you don’t need to change the attachment later a nice generic version:

struct AttachedSlider
{
    AttachedSlider (AudioProcessorValueTreeState& state, const String& paramID, Args&&... args)
    : slider (std::forward<Args>(args)...), attachment (state, paramID, slider)
    {
    }
    Slider slider;
    AudioProcessorValueTreeState::SliderAttachment attachment;
};

#6

Sorry, it’s not easy to explain.

So as a timeline:

(1) Declare SliderAttachment.
(2) Assign SliderAttachment to new attachment. -> Behaves as if attached. Great.
(3) Reassign SliderAttachment via reset() to a different param. -> Behaves as if changed. Great.
(4) Reassign SliderAttachment via reset() to the same param as (2). -> Behaves as if still on (3).


#7

That is indeed strange. I am sorry, I don’t have an idea, how that would happen.


#8

No worries thanks anyway!

Being as we can solve the problem just by calling reset() before reset(new etc.) I think I’ll take that option for now, but I take your point about it possibly being better in the containing component.