init: fix hiding of move constructors of Result<T>
This is needed to have Result<Result<T>> work correctly. Test: init unit tests Change-Id: If7d23d1ea13f3727b567d3baf0eee1d8d0e5a196
This commit is contained in:
parent
4ed58aff38
commit
d1c9cd0499
2 changed files with 51 additions and 2 deletions
|
@ -153,8 +153,14 @@ inline Error ErrnoError() {
|
|||
template <typename T>
|
||||
class Result {
|
||||
public:
|
||||
template <typename... U>
|
||||
Result(U&&... result) : contents_(std::in_place_index_t<0>(), std::forward<U>(result)...) {}
|
||||
Result() {}
|
||||
|
||||
template <typename U, typename... V,
|
||||
typename = std::enable_if_t<!(std::is_same_v<std::decay_t<U>, Result<T>> &&
|
||||
sizeof...(V) == 0)>>
|
||||
Result(U&& result, V&&... results)
|
||||
: contents_(std::in_place_index_t<0>(), std::forward<U>(result),
|
||||
std::forward<V>(results)...) {}
|
||||
|
||||
Result(Error&& error) : contents_(std::in_place_index_t<1>(), error.str(), error.get_errno()) {}
|
||||
Result(const ResultError& result_error)
|
||||
|
|
|
@ -276,6 +276,49 @@ TEST(result, no_copy_on_return) {
|
|||
EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
|
||||
}
|
||||
|
||||
// Below two tests require that we do not hide the move constructor with our forwarding reference
|
||||
// constructor. This is done with by disabling the forwarding reference constructor if its first
|
||||
// and only type is Result<T>.
|
||||
TEST(result, result_result_with_success) {
|
||||
auto return_result_result_with_success = []() -> Result<Result<Success>> {
|
||||
return Result<Success>();
|
||||
};
|
||||
auto result = return_result_result_with_success();
|
||||
ASSERT_TRUE(result);
|
||||
ASSERT_TRUE(*result);
|
||||
|
||||
auto inner_result = result.value();
|
||||
ASSERT_TRUE(inner_result);
|
||||
}
|
||||
|
||||
TEST(result, result_result_with_failure) {
|
||||
auto return_result_result_with_error = []() -> Result<Result<Success>> {
|
||||
return Result<Success>(ResultError("failure string", 6));
|
||||
};
|
||||
auto result = return_result_result_with_error();
|
||||
ASSERT_TRUE(result);
|
||||
ASSERT_FALSE(*result);
|
||||
EXPECT_EQ("failure string", result->error_string());
|
||||
EXPECT_EQ(6, result->error_errno());
|
||||
}
|
||||
|
||||
// This test requires that we disable the forwarding reference constructor if Result<T> is the
|
||||
// *only* type that we are forwarding. In otherwords, if we are forwarding Result<T>, int to
|
||||
// construct a Result<T>, then we still need the constructor.
|
||||
TEST(result, result_two_parameter_constructor_same_type) {
|
||||
struct TestStruct {
|
||||
TestStruct(int value) : value_(value) {}
|
||||
TestStruct(Result<TestStruct> result, int value) : value_(result->value_ * value) {}
|
||||
int value_;
|
||||
};
|
||||
|
||||
auto return_test_struct = []() -> Result<TestStruct> { return {Result<TestStruct>(6), 6}; };
|
||||
|
||||
auto result = return_test_struct();
|
||||
ASSERT_TRUE(result);
|
||||
EXPECT_EQ(36, result->value_);
|
||||
}
|
||||
|
||||
TEST(result, die_on_access_failed_result) {
|
||||
Result<std::string> result = Error();
|
||||
ASSERT_DEATH(*result, "");
|
||||
|
|
Loading…
Reference in a new issue