In many circumstances would it be better to have a JUCE_DECLARE_NON_COPYABLE_AND_NON_MOVABLE?
Discuss
I started trying to formulate a view on this but it gave me a headache pretty quickly.
In many circumstances would it be better to have a JUCE_DECLARE_NON_COPYABLE_AND_NON_MOVABLE?
Discuss
I started trying to formulate a view on this but it gave me a headache pretty quickly.
Well, it depends what you want to happen with your objects. Most of the time when I put JUCE_DECLARE_NON_COPYABLE
on something it’s because I only want one instance of it after creation and I usually don’t really mind where the data ends up, so moving it is fine.
Maybe there’s some demand for JUCE_DECLARE_NON_COPYABLE_AND_NON_MOVABLE
, but I’ve not needed it myself.
If I’m reading this sentence correctly:
Declaring any special member function except a default constructor, even as
=default
or=delete
, will suppress the implicit declaration of a move constructor and move assignment operator.
…deleting the copy operations will effectively disable compiler-generated move operations, so making them as =delete
would be for the sake of being explicit, not to change the compiler’s behavior.
I’m getting the leading edge of your headache now.
If you put JUCE_DECLARE_NON_COPYABLE
on a class then you won’t automatically get a compiler-generated move constructor or assignment operator. This is fine, because it doesn’t prevent you from moving, you just need to explicitly allow it. In most cases when you’ve put JUCE_DECLARE_NON_COPYABLE
in place these are the kinds of things you’ll be worrying about anyway. In this respect JUCE_DECLARE_NON_COPYABLE
acts exactly the same as JUCE_DECLARE_NON_COPYABLE_AND_NON_MOVEABLE
would, but with an escape hatch.
It’s more dangerous when you allow copy construction or assignment, but only specify one of the move constructor/assignment pair. In this case it’s possible to end up unintentionally going via a copy when you attempt to move via the missing one.
In 100% of the cases where I use JUCE_DECLARE_NON_COPYABLE
in my projects, I want non-moveable as well. Usually the object is held by a shared/unique_ptr. I would find a JUCE_DECLARE_NON_COPYABLE_AND_NON_MOVABLE
macro useful, and will probably start using something like that now.
Another case is when you capture this
in a lambda, which is passed to other code. After the object is moved from, the lambda will get called with a this
pointer still pointing to the moved-from instance.