From 7ff6c13a5f1edb13776aa717f82853557b6b8fed Mon Sep 17 00:00:00 2001
From: Sam Yates <halfflat@gmail.com>
Date: Wed, 6 Jul 2016 13:27:46 +0200
Subject: [PATCH] Fix optional<X&> assignment.

* Correct implementation of operator=().
* Unit test for optional reference assignment.
---
 src/util/optional.hpp   | 11 ++++-------
 tests/test_optional.cpp | 19 ++++++++++++++++++-
 2 files changed, 22 insertions(+), 8 deletions(-)

diff --git a/src/util/optional.hpp b/src/util/optional.hpp
index 0955ea99..ddf978d6 100644
--- a/src/util/optional.hpp
+++ b/src/util/optional.hpp
@@ -332,22 +332,19 @@ struct optional<X&>: detail::optional_base<X&> {
     template <typename T>
     optional(optional<T&>& ot): base(ot.set,ot.ref()) {}
 
-    /*
-    template <
-        typename Y,
-        typename = typename std::enable_if<!detail::is_optional<Y>::value>::type>
-    */
     template <typename Y>
     optional& operator=(Y& y) {
         set = true;
-        ref() = y;
+        data.construct(y);
         return *this;
     }
 
     template <typename Y>
     optional& operator=(optional<Y&>& o) {
         set = o.set;
-        data.construct(o);
+        if (o.set) {
+           data.construct(o.get());
+        }
         return *this;
     }
 };
diff --git a/tests/test_optional.cpp b/tests/test_optional.cpp
index aa13e870..6240f53f 100644
--- a/tests/test_optional.cpp
+++ b/tests/test_optional.cpp
@@ -88,6 +88,23 @@ TEST(optionalm,assign_returns) {
     EXPECT_EQ(&a,bp);
 }
 
+TEST(optionalm,assign_reference) {
+    double a=3.0;
+    optional<double &> ar;
+    optional<double &> br;
+
+    ar = a;
+    EXPECT_TRUE(ar);
+    *ar = 5.0;
+    EXPECT_EQ(5.0, a);
+
+    br = ar;
+    EXPECT_TRUE(br);
+
+    *br = 7.0;
+    EXPECT_EQ(7.0, a);
+}
+
 struct nomove {
     int value;
 
@@ -148,7 +165,7 @@ TEST(optionalm,ctor_nocopy) {
     EXPECT_EQ(nocopy(6),b.get());
 }
 
-optional<double> odd_half(int n) {
+static optional<double> odd_half(int n) {
     optional<double> h;
     if (n%2==1) h=n/2.0;
     return h;
-- 
GitLab