From a419dbce2f85ab67fcf18fa38c03875156af7ca2 Mon Sep 17 00:00:00 2001
From: Timo Koch <timo.koch@iws.uni-stuttgart.de>
Date: Wed, 30 Oct 2019 16:25:43 +0000
Subject: [PATCH] [common] Implement fallback for partial for dune 2.6.0

(cherry picked from commit 55fe98b16af5ddf3f2d9a048b16b4b3d358f423d)
---
 dumux/common/partial.hh     | 54 +++++++++++++++++++++++++++++++++++++
 test/common/test_partial.cc |  7 +++++
 2 files changed, 61 insertions(+)

diff --git a/dumux/common/partial.hh b/dumux/common/partial.hh
index 1dc4dbeabd..26b34d832c 100644
--- a/dumux/common/partial.hh
+++ b/dumux/common/partial.hh
@@ -28,9 +28,11 @@
 #include <type_traits>
 
 #include <dune/istl/multitypeblockvector.hh>
+#include <dune/common/version.hh>
 
 namespace Dumux {
 
+#if DUNE_VERSION_GT_REV(DUNE_ISTL,2,6,0)
 /*!
  * \brief a function to get a MultiTypeBlockVector with references to some entries of another MultiTypeBlockVector
  * \param v a MultiTypeBlockVector
@@ -42,6 +44,58 @@ auto partial(Dune::MultiTypeBlockVector<Args...>& v, Dune::index_constant<i>...
     return Dune::MultiTypeBlockVector<std::add_lvalue_reference_t<std::decay_t<std::tuple_element_t<indices, std::tuple<Args...>>>>...>(v[indices]...);
 }
 
+#else
+
+// for backwards-compatibility of partial with v2.6.0
+template<typename ... Args>
+class MultiTypeBlockVectorProxy : public std::tuple<Args...>
+{
+    typedef std::tuple<Args...> ParentType;
+public:
+    using ParentType::ParentType;
+
+    typedef MultiTypeBlockVectorProxy<Args...> type;
+    typedef double field_type;
+
+    /** \brief Random-access operator
+     */
+    template< std::size_t index >
+    typename std::tuple_element<index, ParentType>::type&
+    operator[] ( const std::integral_constant< std::size_t, index > indexVariable )
+    {
+      DUNE_UNUSED_PARAMETER(indexVariable);
+      return std::get<index>(*this);
+    }
+
+    /** \brief Const random-access operator
+     */
+    template< std::size_t index >
+    const typename std::tuple_element<index, ParentType>::type&
+    operator[] ( const std::integral_constant< std::size_t, index > indexVariable ) const
+    {
+      DUNE_UNUSED_PARAMETER(indexVariable);
+      return std::get<index>(*this);
+    }
+};
+
+template<class T> struct isMultiTypeBlockVector;
+
+template<class... T>
+struct isMultiTypeBlockVector<MultiTypeBlockVectorProxy<T...> > : public std::true_type {};
+
+/*!
+ * \brief a function to get a MultiTypeBlockVector with references to some entries of another MultiTypeBlockVector
+ * \param v a MultiTypeBlockVector
+ * \param indices the indices of the entries that should be referenced
+ */
+template<class ...Args, std::size_t ...i>
+auto partial(Dune::MultiTypeBlockVector<Args...>& v, Dune::index_constant<i>... indices)
+{
+    return MultiTypeBlockVectorProxy<std::add_lvalue_reference_t<std::decay_t<std::tuple_element_t<indices, std::tuple<Args...>>>>...>(v[indices]...);
+}
+
+#endif
+
 /*!
  * \brief a function to get a tuple with references to some entries of another tuple
  * \param v a tuple
diff --git a/test/common/test_partial.cc b/test/common/test_partial.cc
index f420efc90a..11ade4186b 100644
--- a/test/common/test_partial.cc
+++ b/test/common/test_partial.cc
@@ -12,6 +12,7 @@
 #include <dune/istl/multitypeblockvector.hh>
 
 #include <dumux/common/partial.hh>
+#include <dune/common/version.hh>
 
 namespace Dumux {
 
@@ -41,8 +42,14 @@ void runTest()
     auto p = partial(m, _0, _2);
     p = partial(m, std::make_tuple(_0, _2));
 
+#if DUNE_VERSION_GT_REV(DUNE_ISTL,2,6,0)
     if (!std::is_same<T<Block1&, Block2&>, std::decay_t<decltype(p)>>::value)
         DUNE_THROW(Dune::Exception, "Dumux::partial() returned wrong type: " << Dune::className(p));
+#else
+    // for dune less or equal than v2.6.0, partial returns a std::tuple
+    if (!(std::is_same<T<Block1&, Block2&>, std::decay_t<decltype(p)>>::value || std::is_same<MultiTypeBlockVectorProxy<Block1&, Block2&>, std::decay_t<decltype(p)>>::value))
+       DUNE_THROW(Dune::Exception, "Dumux::partial() returned wrong type: " << Dune::className(p));
+#endif
 
     std::get<1>(p)[0][0] = 5.0;
 
-- 
GitLab