I know shared_ptr
, unique_ptr
, weak_ptr
are guaranteed to be empty after used as RVR argument in the constructor of the same type, but I wonder does standard specifies this for some other std::
types beside the ones I mentioned.
Please note that I know that elements after move are left in valid but unspecified state, I am here interested for which types state is specified.
A rule of thumb
As a rule of thumb: The move-only types or types with shared reference semantics leave their moved-from object in an empty state. All other types leave unspecified values.
Move-only types
Move-only types (which leave moved-from objects in an empty state) are
std::unique_lock
,std::thread
,std::promise
,std::packaged_task
,std::future
,basic_filebuf
,std::basic_ifstream
,std::basic_ofstream
,std::basic_fstream
,std::shared_lock
andstd::unique_ptr
.Shared reference semantics
Types with shared reference semantics are
std::shared_future
, and of coursestd::shared_ptr
andstd::weak_ptr
. These leave their moved-from objects also in an empty state.A notable exception
As I went through the standard library, I found
std::stringstream
and its input-only and output-only siblings (std::istringstream
andstd::ostringstream
) as a notable exception. These classes are move-only, but nothing is being told about the moved-from object upon move-construction. Therefore, the valid-but-unspecified-rule applies. As you see, it's just a rule of thumb, not 100% always correct.Types leaving moved-from objects in "empty" state are smart pointers, locks ([thread.lock.unique.cons]/21, [thread.lock.shared.cons]/21), file streams ([filebuf.cons]/(4.2)), futures ([futures.unique_future]/(8.2), [futures.shared_future]/10), promises ([futures.promise]/6), packaged tasks ([futures.task]/7), threads ([thread.thread.constr]/10), …
By contrast, templates leaving the moved-from objects with unspecified values are
function
([func.wrap.func.con]/6),basic_regex
([re.regex.construct]/13),basic_string
([string.cons]/2), containers…