[all-commits] [llvm/llvm-project] 27181c: Support: Add Expected<T>::moveInto() to avoid extr...
Duncan P. N. Exon Smith via All-commits
all-commits at lists.llvm.org
Fri Oct 22 11:47:31 PDT 2021
Branch: refs/heads/main
Home: https://github.com/llvm/llvm-project
Commit: 27181cad0d4e48eac822aaccf52b612f29eeff73
https://github.com/llvm/llvm-project/commit/27181cad0d4e48eac822aaccf52b612f29eeff73
Author: Duncan P. N. Exon Smith <dexonsmith at apple.com>
Date: 2021-10-22 (Fri, 22 Oct 2021)
Changed paths:
M llvm/docs/ProgrammersManual.rst
M llvm/include/llvm/Support/Error.h
M llvm/unittests/Support/ErrorTest.cpp
Log Message:
-----------
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
More information about the All-commits
mailing list