Expected<T>::moveInto() takes as an out parameter any OtherT& that's
assignable from T&&. It moves any stored value before returning
takeError().
There are two existing patterns that moveInto() cleans up:
// If the variable is new: Expected<std::unique_ptr<int>> ExpectedP = makePointer(); if (!ExpectedP) return ExpectedP.takeError(); std::unique_ptr<int> P = std::move(*ExpectedP); // If the target variable already exists: if (Expected<T> ExpectedP = makePointer()) P = std::move(*ExpectedP); else return ExpectedP.takeError();
moveInto() takes less typing and avoids needing to name (or leak into
the scope) an extra variable.
// If the variable is new: std::unique_ptr<int> P; if (Error E = makePointer().moveInto(P)) return E; // If the target variable already exists: if (Error E = makePointer().moveInto(P)) return E;
Another use case is writing unit tests, to log errors (but continue)
when there's an unexpected failure. E.g.:
// Crash on error, or undefined in non-asserts builds. std::unique_ptr<MemoryBuffer> MB = cantFail(makeMemoryBuffer()); // Avoid crashing on error without moveInto() :(. Expected<std::unique_ptr<MemoryBuffer>> ExpectedMB = makeMemoryBuffer(); ASSERT_THAT_ERROR(ExpectedMB.takeError(), Succeeded()); std::unique_ptr<MemoryBuffer> MB = std::move(ExpectedMB); // Avoid crashing on error with moveInto() :). std::unique_ptr<MemoryBuffer> MB; ASSERT_THAT_ERROR(makeMemoryBuffer().moveInto(MB), Succeeded());
Should this be && qualified, so it can only be called on a temporary Expected, since it's going to consume it? (I mean takeError isn't rvalue ref qualified and get isn't - so it's not clear it has to be)