Examples of move-only types in the C++ standard library are:

Declaring and Using Move-Only Types

Declaring Move-Only Types

class MoveOnly {
public:
   MoveOnly(MoveOnly&&) noexcept;
   MoveOnly& operator=(MoveOnly) noexcept;
   
   // delete copy ctor and assignment
   MoveOnly(const MoveOnly&) = delete;
   MoveOnly& operator=(const MoveOnly&) = delete;

};

By rule, it would be enough to declare the moving special member function. However, explicitly marking the copying special member function with =delete makes the intention more clear.

Using Move-Only Types

With a declaration like the one above, you can create and move but not copy objects. For example:

std::vector<MoveOnly> coll;

coll.push_back(MoveOnly{}); // OK

MoveOnly mo;
coll.push_back(mo); // ERROR
coll.push_back(std::move(mo)); // OK

To move the value of a move-only element out of the container, simply use std::move() for a reference to the element. For example:

// move assign first element (still there with moved-from state)
mo = std::move(coll[0]);

However, remember that after this call, the element is still in the container with a moved-from state.

Moving out all elements is also possible in loops:

for (auto& elem : coll) {            // note: non-const reference
   coll2.push_back(std::move(elem)); // move element to coll2
}

Again: the elements are still in the container with their moved-from state.

For move-only types, a couple of operations that are usually valid are not possible:

Passing Move-Only Objects as Arguments

Option 1:

void sink(MoveOnly arg);

sink(MoveOnly{}); // OK

MoveOnly mo;
sink(mo); // Error
sink(std::move(mo)); // OK, moves mo to arg

Option 2:

void sink(MoveOnly&& arg);

sink(MoveOnly{}); // OK

MoveOnly mo;
sink(mo); // Error
sink(std::move(mo)); // OK, might move mo to something inside sink()

If it is important for you to give up ownership (because you want to ensure that the file is closed, the thread has stopped, or the associated resource was released), ensure this directly after the call with a corresponding statement. For example:

MoveOnly mo;
foo(std::move(mo));  // might move ownership
// ensure mo’s resource is longer acquired/owned/open/running:
mo.close();   // or mo.reset() or mo.release() or so

Move-only objects usually have such a functions but the names differ (e.g., in the C++ standard library, it is called close() for streams, join() for threads, or reset() for unique pointers). These functions usually bring the objects into a default constructed state.

Returning Move-Only Objects by Value

If you return a local object that way, move semantics is automatically used:

MoveOnly source()
{
   MoveOnly mo;
   ...
   return mo;  // moves mo to the caller
}
MoveOnly m{source()}; // takes ownership of the associated value/resource

Moved-From States of Move-Only Objects

Typically, the check is positive—you ask whether the object still has its resource, not whether it was moved from. Examples include: