Result: Add copy/move ctor/op=
authorChristian Kamm <mail@ckamm.de>
Tue, 8 Jan 2019 13:55:30 +0000 (14:55 +0100)
committerKevin Ottens <kevin.ottens@nextcloud.com>
Tue, 15 Dec 2020 09:58:33 +0000 (10:58 +0100)
It has a destructor and these operations make sense. Particularly the
move is important for code like:

Result<x, y> foo() { Result<x, y> v; return v; }

because the move-ctor will not autogenerate if x or y are not trivially
destructible.

src/common/result.h

index 5db087b54fbd3f7399f5b5afb346e854b3dcce86..61805982e34f39a30323ccd231707a7019853c36 100644 (file)
@@ -43,6 +43,52 @@ public:
     {
     }
 
+    Result(Result &&other)
+        : _isError(other._isError)
+    {
+        if (_isError) {
+            new (&_error) Error(std::move(other._error));
+        } else {
+            new (&_result) T(std::move(other._result));
+        }
+    }
+
+    Result(const Result &other)
+        : _isError(other._isError)
+    {
+        if (_isError) {
+            new (&_error) Error(other._error);
+        } else {
+            new (&_result) T(other._result);
+        }
+    }
+
+    Result &operator=(Result &&other)
+    {
+        if (&other != this) {
+            _isError = other._isError;
+            if (_isError) {
+                new (&_error) Error(std::move(other._error));
+            } else {
+                new (&_result) T(std::move(other._result));
+            }
+        }
+        return *this;
+    }
+
+    Result &operator=(const Result &other)
+    {
+        if (&other != this) {
+            _isError = other._isError;
+            if (_isError) {
+                new (&_error) Error(other._error);
+            } else {
+                new (&_result) T(other._result);
+            }
+        }
+        return *this;
+    }
+
     ~Result()
     {
         if (_isError)
@@ -50,7 +96,9 @@ public:
         else
             _result.~T();
     }
+
     explicit operator bool() const { return !_isError; }
+
     const T &operator*() const &
     {
         ASSERT(!_isError);
@@ -61,6 +109,13 @@ public:
         ASSERT(!_isError);
         return std::move(_result);
     }
+
+    const T *operator->() const
+    {
+        ASSERT(!_isError);
+        return &_result;
+    }
+
     const Error &error() const &
     {
         ASSERT(_isError);