From d776f9aa21e29d8733963028ad628bea46e0fddd Mon Sep 17 00:00:00 2001
From: Sam Yates <sam@quux.dropbear.id.au>
Date: Thu, 13 Oct 2016 17:05:37 +0200
Subject: [PATCH] Make lambda transform iterators copy-ssignable.

---
 src/util/transform.hpp | 36 +++++++++++++++++++++++++++++-------
 1 file changed, 29 insertions(+), 7 deletions(-)

diff --git a/src/util/transform.hpp b/src/util/transform.hpp
index a5ab0b34..046b201e 100644
--- a/src/util/transform.hpp
+++ b/src/util/transform.hpp
@@ -23,7 +23,7 @@ class transform_iterator: public iterator_adaptor<transform_iterator<I, F>, I> {
     friend class iterator_adaptor<transform_iterator<I, F>, I>;
 
     I inner_;
-    F f_;
+    uninitialized<F> f_; // always in initialized state post-construction
 
     // provides access to inner iterator for adaptor.
     const I& inner() const { return inner_; }
@@ -40,17 +40,39 @@ public:
     transform_iterator() = default;
 
     template <typename J, typename G>
-    transform_iterator(J&& c, G&& g): inner_(std::forward<J>(c)), f_(std::forward<G>(g)) {}
+    transform_iterator(J&& c, G&& g): inner_(std::forward<J>(c)) {
+        f_.construct(std::forward<G>(g));
+    }
+
+    transform_iterator(const transform_iterator& other): inner_(other.inner_) {
+        f_.construct(other.f_.cref());
+    }
+
+    transform_iterator(transform_iterator&& other): inner_(std::move(other.inner_)) {
+        f_.construct(std::move(other.f_.ref()));
+    }
+
+    transform_iterator& operator=(transform_iterator&& other) {
+        if (this!=&other) {
+            inner_ = std::move(other.inner_);
+            f_.construct(std::move(other.f_.ref()));
+        }
+        return *this;
+    }
 
-    transform_iterator(const transform_iterator&) = default;
-    transform_iterator(transform_iterator&&) = default;
-    transform_iterator& operator=(const transform_iterator&) = default;
-    transform_iterator& operator=(transform_iterator&&) = default;
+    transform_iterator& operator=(const transform_iterator& other) {
+        if (this!=&other) {
+            inner_ = other.inner_;
+            f_.destruct();
+            f_.construct(other.f_.cref());
+        }
+        return *this;
+    }
 
     // forward and input iterator requirements
 
     value_type operator*() const {
-        return f_(*inner_);
+        return f_.cref()(*inner_);
     }
 
     util::pointer_proxy<value_type> operator->() const {
-- 
GitLab