Some people might ask why I chose to make
the parameter of BlackBox::store an rvalue
reference rather than an lvalue reference
and force the client code to use std::move.
While it is true that an lvalue reference
would also have worked, if I did that, it
would be impossible to write code like
crate.store(std::make_unique<Gadget>(beeper, flasher));.
I also happen to think that forcing the client to use
std::move at the call sites is good rather than bad,
because it communicates the intended effect to the reader.Exactly. Instead of understanding the very simple concept of which object owns, I now have to understand that concept, how std::unique_ptr works, and rvalue references? How does it work with conditional ownage?
I also mostly use C instead of C++, but I admit that automatic constructor/destructor calls and virtual functions (as long as the class hierarchy doesn't become too deep) are quite useful. Lambda expressions too. I think that as long as you can use C++ while still having an idea what the language is doing implicitly what you would've had to do explicitly in C, you can get the advantages without the disadvantages.
While one concept is simpler, the other is controlled by compiler, while object ownership is only controlled by the developer himself.
And in my opionion, if you want safety quarantees like that, use Rust. I was a fan of the new C++ standards a while ago, but after having used them for some time, I found C is a lot nicer language. There's just way too much mental overhead when trying to write "idiomatic C++" and the compiler errors you sometimes get are just a waste of developer time.