An explicit move constructors can affect compatibility with e.g. Standard algorithms. For instance, std::swap<T> requires that T be MoveConstructible. In turn, MoveConstructible is specified in terms of an expression, namely T u = rv; (where rv is an rvalue of type T).
If there is neither a non-explicit copy constructor nor a non-explicit move constructor for a given type then T u = rv; is invalid and that type can’t be used with std::swap. (In this particular instance however it is possible to specialize std::swap to provide the desired functionality, e.g. by using T u(rv);).
Put more simply, an explicit move or copy constructor defies expectations and can’t be used as well with generic code.
Some other parts of the Standard library that put a MoveConstructible requirement:
- the deleter of
unique_ptr<T, D> - call wrappers, used in e.g.
bind(all the decayed types that are passed are concerned) thread,async,call_once(all specified in terms of call wrappers)sort,stable_sort,nth_element,sort_heap