When calling left()/right()/left_opt()/right_opt() on a rvalue reference, it performs a move and returns a rvalue reference

This commit is contained in:
Sebastian Messmer 2015-06-28 17:25:13 +02:00
parent 7ae30280f3
commit 72cb9fa038
2 changed files with 48 additions and 8 deletions

View File

@ -75,49 +75,69 @@ namespace cpputils {
return _side == Side::right; return _side == Side::right;
} }
const Left &left() const { const Left &left() const& {
return _left; return _left;
} }
Left &left() { Left &left() & {
return const_cast<Left&>(const_cast<const Either<Left, Right>*>(this)->left()); return const_cast<Left&>(const_cast<const Either<Left, Right>*>(this)->left());
} }
Left &&left() && {
return std::move(left());
}
const Right &right() const { const Right &right() const& {
return _right; return _right;
} }
Right &right() { Right &right() & {
return const_cast<Right&>(const_cast<const Either<Left, Right>*>(this)->right()); return const_cast<Right&>(const_cast<const Either<Left, Right>*>(this)->right());
} }
Right &&right() && {
return std::move(right());
}
boost::optional<const Left&> left_opt() const { boost::optional<const Left&> left_opt() const& {
if (_side == Side::left) { if (_side == Side::left) {
return _left; return _left;
} else { } else {
return boost::none; return boost::none;
} }
} }
boost::optional<Left&> left_opt() { boost::optional<Left&> left_opt() & {
if (_side == Side::left) { if (_side == Side::left) {
return _left; return _left;
} else { } else {
return boost::none; return boost::none;
} }
} }
boost::optional<Left> left_opt() && {
if (_side == Side::left) {
return std::move(_left);
} else {
return boost::none;
}
}
boost::optional<const Right&> right_opt() const { boost::optional<const Right&> right_opt() const& {
if (_side == Side::right) { if (_side == Side::right) {
return _right; return _right;
} else { } else {
return boost::none; return boost::none;
} }
} }
boost::optional<Right&> right_opt() { boost::optional<Right&> right_opt() & {
if (_side == Side::right) { if (_side == Side::right) {
return _right; return _right;
} else { } else {
return boost::none; return boost::none;
} }
} }
boost::optional<Right> right_opt() && {
if (_side == Side::right) {
return std::move(_right);
} else {
return boost::none;
}
}
private: private:
union { union {

View File

@ -341,6 +341,26 @@ TEST_F(EitherTest, MakeRight_MultiParam) {
EXPECT_RIGHT_IS(make_pair(4,5), var); EXPECT_RIGHT_IS(make_pair(4,5), var);
} }
TEST_F(EitherTest, LeftCanBeQueriedAsRvalue) {
OnlyMoveable val = make_left<OnlyMoveable, int>(3).left();
EXPECT_EQ(OnlyMoveable(3), val);
}
TEST_F(EitherTest, RightCanBeQueriedAsRvalue) {
OnlyMoveable val = make_right<int, OnlyMoveable>(3).right();
EXPECT_EQ(OnlyMoveable(3), val);
}
TEST_F(EitherTest, LeftOptCanBeQueriedAsRvalue) {
OnlyMoveable val = make_left<OnlyMoveable, int>(3).left_opt().value();
EXPECT_EQ(OnlyMoveable(3), val);
}
TEST_F(EitherTest, RightOptCanBeQueriedAsRvalue) {
OnlyMoveable val = make_right<int, OnlyMoveable>(3).right_opt().value();
EXPECT_EQ(OnlyMoveable(3), val);
}
class DestructorCallback { class DestructorCallback {
public: public:
MOCK_CONST_METHOD0(call, void()); MOCK_CONST_METHOD0(call, void());