You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In spite of the fact last statement is a rvalue copy object is created by using of T(T&&) move-constructor (if any) for Result<T>/Result<T&> situation and T::T(const T&) copy-constructor (if any) for Result<const T&>
This behavior produces several undesirable side effects of using VERIFY_RESULT:
can't be used for functions/methods which returns Result with non-copyable T even in Result<T&>/Result<const T&> form
In case T is moveable returning of Result<T&> from function/method original object of T will be set to unspecified state
Result<vector<int>&> GetData() {
return data_;
}
simple calling of VERIFY_RESULT(obj.GetData()) will set obj's data_ field to unspecified state (state of moved from object)
In case T is copyable but not moveable returning of Result<T&>/Result<const T&> creates undesirable copy of T
d-uspenskiy
changed the title
VERIFY_RESULT creates undesirable copy of Result value
VERIFY_RESULT creates undesirable copy of Result<T&>'s value
Sep 13, 2019
Summary:
1. `VERIFY_RESULT` and similar macros uses GNU expression statement `__extension__`
```
#define VERIFY_RESULT(expr) \
__extension__ ({ auto&& __result = (expr); RETURN_NOT_OK(__result); std::move(*__result); })
```
In spite of the fact last statement is a rvalue reference copy object is created by using of `T(T&&)` move-constructor (if any) for `Result<T>/Result<T&>` situation and `T::T(const T&)` copy-constructor (if any) for `Result<const T&>`
To avoid undesirable copying of `T` object in case of `Result<T&>` and `Result<const T&>` `std::reference_wrapper<T>` is returned from expression statement `__extension__`.
As of now `VERIFY_RESULT` and similar macros returns `std::reference_wrapper<T>` for `Result<T&>/Result<const T&>` situation new helper macro `VERIFY_RESULT_REF` is introduced (it is still safe to use `VERIFY_RESULT` in this situation).
It is useful with `auto`:
```
Result<const vector<int>&> GetVector() {
static const vector<int> values{1, 2, 3};
return values;
}
const auto& value = VERIFY_RESULT_REF(GetVector());
...
for(const auto& i : VERIFY_RESULT_REF(GetVector())) {
...
}
```
2. Make `Status::OK()` be a wrapper to avoid creation of `Result<T>` from it at compile time
Test Plan:
New unit test was introduced
```
./yb_build.sh --cxx-test result-test
```
Reviewers: mikhail, sergei
Reviewed By: sergei
Subscribers: bogdan, ybase
Differential Revision: https://phabricator.dev.yugabyte.com/D7204
VERIFY_RESULT
and similar macros uses GNU expression statement__extension__
In spite of the fact last statement is a rvalue copy object is created by using of
T(T&&)
move-constructor (if any) forResult<T>/Result<T&>
situation andT::T(const T&)
copy-constructor (if any) forResult<const T&>
This behavior produces several undesirable side effects of using
VERIFY_RESULT
:Result
with non-copyableT
even inResult<T&>/Result<const T&>
formT
is moveable returning ofResult<T&>
from function/method original object ofT
will be set to unspecified statesimple calling of
VERIFY_RESULT(obj.GetData())
will set obj'sdata_
field to unspecified state (state ofmoved from
object)T
is copyable but not moveable returning ofResult<T&>/Result<const T&>
creates undesirable copy ofT
each call of
VERIFY_RESULT(obj.GetLargeData())
will create map's copyThe text was updated successfully, but these errors were encountered: