From 72cb9fa03844a70d37086f11b8b1064c337e4293 Mon Sep 17 00:00:00 2001 From: Sebastian Messmer Date: Sun, 28 Jun 2015 17:25:13 +0200 Subject: [PATCH] When calling left()/right()/left_opt()/right_opt() on a rvalue reference, it performs a move and returns a rvalue reference --- either.h | 36 ++++++++++++++++++++++++++++-------- test/EitherTest.cpp | 20 ++++++++++++++++++++ 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/either.h b/either.h index c4d55384..dfbd8086 100644 --- a/either.h +++ b/either.h @@ -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(const_cast*>(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(const_cast*>(this)->right()); } + Right &&right() && { + return std::move(right()); + } - boost::optional left_opt() const { + boost::optional left_opt() const& { if (_side == Side::left) { return _left; } else { return boost::none; } } - boost::optional left_opt() { + boost::optional left_opt() & { if (_side == Side::left) { return _left; } else { return boost::none; } } + boost::optional left_opt() && { + if (_side == Side::left) { + return std::move(_left); + } else { + return boost::none; + } + } - boost::optional right_opt() const { + boost::optional right_opt() const& { if (_side == Side::right) { return _right; } else { return boost::none; } } - boost::optional right_opt() { + boost::optional right_opt() & { if (_side == Side::right) { return _right; } else { return boost::none; } } + boost::optional right_opt() && { + if (_side == Side::right) { + return std::move(_right); + } else { + return boost::none; + } + } private: union { diff --git a/test/EitherTest.cpp b/test/EitherTest.cpp index 9b8c4edd..f6427f43 100644 --- a/test/EitherTest.cpp +++ b/test/EitherTest.cpp @@ -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(3).left(); + EXPECT_EQ(OnlyMoveable(3), val); +} + +TEST_F(EitherTest, RightCanBeQueriedAsRvalue) { + OnlyMoveable val = make_right(3).right(); + EXPECT_EQ(OnlyMoveable(3), val); +} + +TEST_F(EitherTest, LeftOptCanBeQueriedAsRvalue) { + OnlyMoveable val = make_left(3).left_opt().value(); + EXPECT_EQ(OnlyMoveable(3), val); +} + +TEST_F(EitherTest, RightOptCanBeQueriedAsRvalue) { + OnlyMoveable val = make_right(3).right_opt().value(); + EXPECT_EQ(OnlyMoveable(3), val); +} + class DestructorCallback { public: MOCK_CONST_METHOD0(call, void());