How would writing
void setSomething(unique_ptr<Component> b)
{
b->doSomething();
container.push_back(std::move(b));
/// many lines of code
if (someRareCondition())
b->doSomethingElse();
}
with a ScopedPointer be any different?
How would writing
void setSomething(unique_ptr<Component> b)
{
b->doSomething();
container.push_back(std::move(b));
/// many lines of code
if (someRareCondition())
b->doSomethingElse();
}
with a ScopedPointer be any different?
Well in the pre unique days you’d make a bare pointer with new and pass it in and then when you shoved it in an RAII container the pointer will still be valid and it’s pretty convenient.
You could do something like create a component. Shove it into a container and then use the pointer to call other functions on the object you’ve put in the container.
Now if you want to do that you have to put it in the container last as otherwise your unique ptr will nullptr when you call these other functions.
There are a few ways to access the object later but they are all a bit icky, verbose or only work in certain circumstances.
And it was less typing, and the compiler errors from calling new wrong didn’t go on for 3 pages 
Anyway this is just my moaning for the day…
I might write something in assembly to make me feel better ….
No one imposes their best practice opinions on you in machine code.

You can still do that.
std::vector<std::unique_ptr<Component>> container;
void addToContainer(Component* newComp)
{
container.emplace_back(newComp);
//call other functions on newComp
}
//Then use like:
addToContainer(new TextButton(...));
JAVA does this everywhere I think though? Maybe I’m wrong….
Java is garbage collected, but yeah, it’s probably still easy to do there.
Yeah. But that I would say misses the benefit people are arguing for, that the taking ownership is clear. And doesn’t work when someone else wrote addToContainer and demands you pass it a unique ptr!
I think of garbage collection as a sharedptr where some other thread does a delete later…
I’m probably over simplifying it.
Edit: my point being it’s maybe possible to do a whole c++ epic in shared ptr safely, but personally I like to know when my objects are getting trashed ![]()
Yes, that’s generally considered one of the huge benefits of C++, determinism.
My wish is a completely different one, that would still resolve the problem.
If push_back() only could return an iterator to the added object… you could continue using the added object indirectly.
FTFY
I know someone who has written their DSP in Java - they used Juce to Render the plug-in(!) and ‘HotSpot’ Java for the DSP.
I know right, sheer madness, hey?! It all works pretty well though…
add in OwnedArray does this
Wish I’d noticed years ago 
That’s the benefit if you write your API yourself and you don’t have to convince hundreds of engineers in the iso committee…
Just reading on, you can do:
auto& newElement = vec.insert (vec.end(), std::make_unique<Foo>());
newElement->bar();
nice, eh?
Now you can even write your own
std::vector<T, Allocator>::iterator push_back (std::vector<T, Allocator> vec, T&& newElement)
{
return vec.insert (vec.end(), newElement);
}
// using it:
addAndMakeVisible (*push_back (vector, std::make_unique<Foo>()));
// or like above:
auto& foo = push_back (vector, std::make_unique<Foo>());
foo->bar();
but haven’t tested it
It will probably work in VS, but in XCode it should be:
auto newElement = vec.insert (vec.end(), std::make_unique<Foo>());
newElement->get()->bar();
or
const auto& newElement = vec.insert (vec.end(), std::make_unique<Foo>());
newElement->get()->bar();
This will also work:
template <typename T>
auto push_back_and_return_object (std::vector<std::unique_ptr<T>>& vec, std::unique_ptr<T>&& newElement)
{
return vec.insert (vec.end(), std::move (newElement))->get();
}
...
std::vector<std::unique_ptr<Foo>> vec;
addAndMakeVisible (push_back_and_return_object (vec, std::make_unique<Foo>()));
or in more general form: ![]()
template <typename T, typename Allocator, template <typename, typename> class V>
auto push_back_and_return_object (V<T, Allocator>& vec, T&& newElement)
{
return vec.insert (vec.end(), std::move (newElement))->get();
}
...
std::vector<std::unique_ptr<Foo>> vec;
addAndMakeVisible (push_back_and_return_object (vec, std::make_unique<Foo>()));
Edit: Daniel’s initial version of push_back will also work with these corrections:
template <typename T, typename Allocator>
auto push_back_and_return_object (std::vector<T, Allocator>& vec, T&& newElement)
{
return vec.insert (vec.end(), std::move (newElement))->get();
}
...
std::vector<std::unique_ptr<Foo>> vec;
addAndMakeVisible (push_back_and_return_object (vec, std::make_unique<Foo>()));
In many situations you could use emplace_back() which has the advantage that it returns a reference to the added element. IMO this is the most important and most useful difference between emplace_back() and push_back() 
Yes, but in case you store unique_ptr’s in std::vector, one should use push_back with std::move. With emplace_back there will be a memory leak if extending std::vector fails.
That’s an interesting point I haven’t thought about 
Is it still a problem when using make_unique like this?
std::vector<std::unique_ptr<MyClass>> vec;
auto& obj = vec.emplace_back(std::make_unique<MyClass>());
As far as I understand it this implicitly moves the newly created unique_ptr into the vector and if it fails the unique_ptr is getting destroyed because it get’s out of scope.
the most important difference is that push_back calls the object’s copy constructor, while emplace_back constructs the new object in place in the vector
Yes, therefore this will fail:
std::vector<std::unique_ptr<MyClass>> vec;
auto& obj = vec.emplace_back (std::make_unique<MyClass>());
Instead it should be:
std::vector<std::unique_ptr<MyClass>> vec;
auto& obj = vec.emplace_back (new MyClass());
But if something goes wrong, for example vector is too small, it will cause problems.
Looks like it works to me… Compiler Explorer