StretchableLayoutManager::layoutComponents with std::weak_ptr instead of raw pointers

I’m working with the StretchableLayoutManager, building a list of components for it to manage. It currently takes an array of raw pointers:

 void layOutComponents (Component** components,
                           int numComponents,
                           int x, int y, int width, int height,
                           bool vertically,
                           bool resizeOtherDimension);

It would be nice if there was an overload for layoutComponents that took std::vector<std::weak_ptr>> so I can use a std::shared_ptr for storing each Component.

 void layOutComponents (std::vector<std::weak_ptr>> components,
                           int numComponents,
                           int x, int y, int width, int height,
                           bool vertically,
                           bool resizeOtherDimension);

maybe it’s better to take an std::function in that case so you can do whatever to wrap your own data ?

I would strongly advise against organising Components in shared_ptr, since cross referencing almost certainly leads to a circular reference blocking the destruction.

The juce-way would be to use an Array or vector of Component::SafePointer, since it’s already Components.

Having said that, looking into the sources, the layOutComponents doesn’t keep the pointers anyway, and if they were to be destroyed outside the message thread, we would be in undefined behaviour anyway. So maybe it doesn’t need to be changed at all, you just have the overhead of converting that array of components into pointers.
That should probably be implemented in a free function, since everybody will use a different container to store the components, if it is a container at all.

span<Component*>

c++20 :slight_smile:

juce::span<Component*>?

Not sure this would help massively, you’d still need a contiguous region holding Component*s which isn’t easy to produce from a vector<shared_ptr<Component>> without an intermediate container.

The idiomatic way to do this is to have the function take a templated range or iterator-pair, then to use something like a TransformIterator to convert containers that don’t directly provide appropriate iterators. That makes the interface look a bit scary, though, and it’s not a very JUCEy way of doing things.

Well one of the advantages of span is that it can be constructed from an iterator pair so you could feed it with a std::vector, juce::Array etc. It does need to be a contiguous array though so I don’t think that would work with std::list etc.

In an ideal world it would probably take a range so you can do all the transforms on that using STL but that really is C++20.

Also I need a span so if I can use one provided in juce it would make my life easier :wink:

1 Like

Currently I am storing the Components in a std::vector<Component*> which is not too bad because I still have direct access to the data with std::vector::data()

I just have an aversion to raw pointers :slight_smile:

You could try OwnedArray if you need proper RAII semantics while retaining the ability to extract an array of raw pointers via OwnedArray::data.

1 Like