From 2ee20575b944d16d44528653aa4ae158099493c8 Mon Sep 17 00:00:00 2001
From: Philip Trettner <Philip.Trettner@rwth-aachen.de>
Date: Fri, 2 Oct 2020 14:07:00 +0200
Subject: [PATCH] fixed attribute views

---
 src/polymesh/attributes.hh           |  8 +++++---
 src/polymesh/impl/impl_attributes.hh |  9 ++++++++-
 src/polymesh/view.hh                 | 22 ++++++++++++++--------
 3 files changed, 27 insertions(+), 12 deletions(-)

diff --git a/src/polymesh/attributes.hh b/src/polymesh/attributes.hh
index d30c5b8..8e3688f 100644
--- a/src/polymesh/attributes.hh
+++ b/src/polymesh/attributes.hh
@@ -108,11 +108,13 @@ public:
     void compute(FuncT&& f);
 
     template <class FuncT>
-    auto view(FuncT&& f) const -> attribute_view<primitive_attribute<tag, AttrT> const&, FuncT>;
-#ifndef _MSC_VER // cannot overload this apparently
+    auto view(FuncT&& f) & -> attribute_view<primitive_attribute<tag, AttrT>&, FuncT>;
+    template <class FuncT>
+    auto view(FuncT&& f) const& -> attribute_view<primitive_attribute<tag, AttrT> const&, FuncT>;
     template <class FuncT>
     void view(FuncT&& f) && = delete;
-#endif
+    template <class FuncT>
+    void view(FuncT&& f) const&& = delete;
 
     // template <class ReadT, class WriteT>
     // auto view(ReadT&& r, WriteT&& w) -> readwrite_property<primitive_attribute<tag, AttrT>, ReadT, WriteT>;
diff --git a/src/polymesh/impl/impl_attributes.hh b/src/polymesh/impl/impl_attributes.hh
index b8aa5a8..470586c 100644
--- a/src/polymesh/impl/impl_attributes.hh
+++ b/src/polymesh/impl/impl_attributes.hh
@@ -439,9 +439,16 @@ void primitive_attribute<tag, AttrT>::compute(FuncT&& f)
 
 template <class tag, class AttrT>
 template <class FuncT>
-auto primitive_attribute<tag, AttrT>::view(FuncT&& f) const -> attribute_view<primitive_attribute<tag, AttrT> const&, FuncT>
+auto primitive_attribute<tag, AttrT>::view(FuncT&& f) const& -> attribute_view<primitive_attribute<tag, AttrT> const&, FuncT>
 {
     return attribute_view<primitive_attribute<tag, AttrT> const&, FuncT>(*this, std::forward<FuncT>(f));
 }
 
+template <class tag, class AttrT>
+template <class FuncT>
+auto primitive_attribute<tag, AttrT>::view(FuncT&& f) & -> attribute_view<primitive_attribute<tag, AttrT>&, FuncT>
+{
+    return attribute_view<primitive_attribute<tag, AttrT>&, FuncT>(*this, std::forward<FuncT>(f));
+}
+
 } // namespace polymesh
diff --git a/src/polymesh/view.hh b/src/polymesh/view.hh
index 86e64ef..f0a7065 100644
--- a/src/polymesh/view.hh
+++ b/src/polymesh/view.hh
@@ -8,30 +8,36 @@ namespace polymesh
 template <class CollectionT, class FuncT>
 struct attribute_view
 {
-    attribute_view(CollectionT collection, FuncT func) : mCollection(collection), mFunc(std::move(func)) {}
+    attribute_view(CollectionT& collection, FuncT func) : mCollection(collection), mFunc(std::move(func)) {}
 
     using index_t = typename std::decay<CollectionT>::type::index_t;
     using handle_t = typename std::decay<CollectionT>::type::handle_t;
     using input_t = decltype(std::declval<CollectionT>()[index_t()]);
     using output_t = typename tmp::decayed_result_type_of<FuncT, input_t>;
 
-    output_t operator[](handle_t h) const { return mFunc(mCollection(h)); }
-    output_t operator[](index_t h) const { return mFunc(mCollection(h)); }
+    decltype(auto) operator[](handle_t h) const { return mFunc(mCollection(h)); }
+    decltype(auto) operator[](index_t h) const { return mFunc(mCollection(h)); }
 
-    output_t operator()(handle_t h) const { return mFunc(mCollection(h)); }
-    output_t operator()(index_t h) const { return mFunc(mCollection(h)); }
+    decltype(auto) operator()(handle_t h) const { return mFunc(mCollection(h)); }
+    decltype(auto) operator()(index_t h) const { return mFunc(mCollection(h)); }
+
+    decltype(auto) operator[](handle_t h) { return mFunc(mCollection(h)); }
+    decltype(auto) operator[](index_t h) { return mFunc(mCollection(h)); }
+
+    decltype(auto) operator()(handle_t h) { return mFunc(mCollection(h)); }
+    decltype(auto) operator()(index_t h) { return mFunc(mCollection(h)); }
 
     int size() const { return mCollection.size(); }
 
     template <class F>
     auto map(F&& f) const
     {
-        auto f2 = [ff = std::forward<F>(f)](output_t const& v) { return ff(v); };
-        return attribute_view<CollectionT, decltype(f2)>(mCollection, std::move(f2));
+        auto new_f = [f0 = mFunc, f1 = std::forward<F>(f)](auto&& v) -> decltype(auto) { return f1(f0(v)); };
+        return attribute_view<CollectionT, decltype(new_f)>(mCollection, std::move(new_f));
     }
 
 private:
-    CollectionT mCollection;
+    CollectionT& mCollection;
     FuncT mFunc;
 };
 }
-- 
GitLab