Support: Add Expected<T>::moveInto() to avoid extra names
Expected<T>::moveInto() takes as an out parameter any `OtherT&` that's assignable from `T&&`. It moves any stored value before returning takeError(). Since moveInto() consumes both the Error and the value, it's only anticipated that we'd use call it on temporaries/rvalues, with naming the Expected first likely to be an anti-pattern of sorts (either you want to deal with both at the same time, or you don't). As such, starting it out as `&&`-qualified... but it'd probably be fine to drop that if there's a good use case for lvalues that appears. There are two common 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; ``` It also seems useful for 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()); ``` Differential Revision: https://reviews.llvm.org/D112278
Loading
Please sign in to comment