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;
}
const Left &left() const {
const Left &left() const& {
return _left;
}
Left &left() {
Left &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;
}
Right &right() {
Right &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) {
return _left;
} else {
return boost::none;
}
}
boost::optional<Left&> left_opt() {
boost::optional<Left&> left_opt() & {
if (_side == Side::left) {
return _left;
} else {
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) {
return _right;
} else {
return boost::none;
}
}
boost::optional<Right&> right_opt() {
boost::optional<Right&> right_opt() & {
if (_side == Side::right) {
return _right;
} else {
return boost::none;
}
}
boost::optional<Right> right_opt() && {
if (_side == Side::right) {
return std::move(_right);
} else {
return boost::none;
}
}
private:
union {

View File

@ -341,6 +341,26 @@ TEST_F(EitherTest, MakeRight_MultiParam) {
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 {
public:
MOCK_CONST_METHOD0(call, void());