After reading this recent question by @Mehrdad on which classes should be made non-movable and therefore non-copyable, I starting wondering if there are use cases for a class which can be copied but not moved. Technically, this is possible:
struct S
{
S() { }
S(S const& s) { }
S(S&&) = delete;
};
S foo()
{
S s1;
S s2(s1); // OK (copyable)
return s1; // ERROR! (non-movable)
}
Although S
has a copy constructor, it obviously does not model the CopyConstructible
concept, because that is in turn a refinement of the MoveConstructible
concept, which requires the presence of a (non-deleted) move constructor (see § 17.6.3.1/2, Table 21).
Is there any use case for a type like S
above, which is copyable but not CopyConstructible
and non-movable? If not, why is it not forbidden to declare a copy constructor and a deleted move constructor in the same class?
class NonCopyable { public: NonCopyable (const NonCopyable &) = delete; NonCopyable & operator = (const NonCopyable &) = delete; protected: NonCopyable () = default; ~NonCopyable () = default; /// Protected non-virtual destructor }; class CantCopy : private NonCopyable {};
There are three ways to prevent such an object copy: keeping the copy constructor and assignment operator private, using a special non-copyable mixin, or deleting those special member functions. A class that represents a wrapper stream of a file should not have its instance copied around.
Abstract Classes should be non copy-assignable.
Suppose you have a class that is no cheaper to move than it is to copy (perhaps it contains a std::array
of a POD type).
Functionally, you "should" make it MoveConstructible so that S x = std::move(y);
behaves like S x = y;
, and that's why CopyConstructible is a sub-concept of MoveConstructible. Usually if you declare no constructors at all, this "just works".
In practice, I suppose that you might want to temporarily disable the move constructor in order to detect whether there is any code in your program that appears more efficient than it really is, by moving instances of S
. To me it seems excessive to forbid that. It's not the standard's job to enforce good interface design in completed code :-)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With