diff --git a/src/amdis/Assembler.hpp b/src/amdis/Assembler.hpp
index cd1aaa75031e41466960b65e259506b396d73bbf..6c1c83620c32b9cb1e1e295e9f038eada426a96f 100644
--- a/src/amdis/Assembler.hpp
+++ b/src/amdis/Assembler.hpp
@@ -138,7 +138,7 @@ namespace AMDiS
   template <class LocalContext, class Operator, class... Nodes>
   auto makeAssembler(Operator&& op, Nodes const&...)
   {
-    return Assembler<LocalContext, Underlying_t<Operator>, Nodes...>{std::forward<Operator>(op)};
+    return Assembler<LocalContext, Underlying_t<Operator>, Nodes...>{FWD(op)};
   }
 
 } // end namespace AMDiS
diff --git a/src/amdis/DataTransfer.inc.hpp b/src/amdis/DataTransfer.inc.hpp
index 799009cd77f4bedfad5b7e8fda0c164c8808104c..3946f17f9c552ecf19d348ee507020b7a46e9b8c 100644
--- a/src/amdis/DataTransfer.inc.hpp
+++ b/src/amdis/DataTransfer.inc.hpp
@@ -82,8 +82,7 @@ namespace AMDiS
       }
     };
 
-    using NodeDataTransferContainer = std::decay_t<decltype(
-      makeTreeContainer<Tree, NDT>(std::declval<const Tree&>(), NDT()))>;
+    using NodeDataTransferContainer = TYPEOF(makeTreeContainer<Tree, NDT>(std::declval<const Tree&>(), NDT()));
 
     // Returns the Node's NodeElementData
     struct NodeElementData
@@ -97,8 +96,7 @@ namespace AMDiS
       }
     };
 
-    using ElementData = std::decay_t<decltype(
-      makeTreeContainer<Tree, NodeElementData>(std::declval<const Tree&>(), NodeElementData()))>;
+    using ElementData = TYPEOF(makeTreeContainer<Tree, NodeElementData>(std::declval<const Tree&>(), NodeElementData()));
 
   public:
     // Container with data that persists during grid adaptation
diff --git a/src/amdis/DirichletBC.hpp b/src/amdis/DirichletBC.hpp
index 344d10763c34c1b3c5811195a127aafe28f278a8..10e932b947ec299bdbc3f6687ef26696ad5597dc 100644
--- a/src/amdis/DirichletBC.hpp
+++ b/src/amdis/DirichletBC.hpp
@@ -41,16 +41,16 @@ namespace AMDiS
     template <class BM, class Values,
       REQUIRES(Concepts::Functor<Values, Range(Domain)>) >
     DirichletBC(BM&& boundaryManager, BoundaryType id, Values&& values)
-      : Super(std::forward<BM>(boundaryManager), id)
-      , values_(std::forward<Values>(values))
+      : Super(FWD(boundaryManager), id)
+      , values_(FWD(values))
     {}
 
     template <class Predicate, class Values,
       REQUIRES(Concepts::Functor<Predicate, bool(Domain)>),
       REQUIRES(Concepts::Functor<Values, Range(Domain)>)>
     DirichletBC(Predicate&& predicate, Values&& values)
-      : predicate_(std::forward<Predicate>(predicate))
-      , values_(std::forward<Values>(values))
+      : predicate_(FWD(predicate))
+      , values_(FWD(values))
     {}
 
     template <class Intersection>
diff --git a/src/amdis/GridFunctionOperator.hpp b/src/amdis/GridFunctionOperator.hpp
index b33394536a1ad8db018247b52fa6fee7c3a62a35..18d93071e19b9188c05ecfa5ba10557fc0f93556 100644
--- a/src/amdis/GridFunctionOperator.hpp
+++ b/src/amdis/GridFunctionOperator.hpp
@@ -70,7 +70,7 @@ namespace AMDiS
      **/
     template <class GF>
     GridFunctionOperatorBase(GF&& gridFct, int termOrder)
-      : gridFct_(std::forward<GF>(gridFct))
+      : gridFct_(FWD(gridFct))
       , termOrder_(termOrder)
     {}
 
@@ -80,7 +80,7 @@ namespace AMDiS
     {
       using ctype = typename Geometry::ctype;
       quadFactory_.emplace(
-        makeQuadratureFactory<ctype, LocalContext::mydimension, LocalFunction>(std::forward<PreQuadFactory>(pre)));
+        makeQuadratureFactory<ctype, LocalContext::mydimension, LocalFunction>(FWD(pre)));
     }
 
   protected:
@@ -157,14 +157,14 @@ namespace AMDiS
     template <class... Args,
       std::enable_if_t<Dune::Std::is_detected<Constructable, Transposed, Args...>::value, int> = 0>
     GridFunctionOperatorTransposed(Args&&... args)
-      : transposedOp_(std::forward<Args>(args)...)
+      : transposedOp_(FWD(args)...)
     {}
 
     /// Redirects the setQuadFactory call top the transposed operator
     template <class PreQuadFactory>
     void setQuadFactory(PreQuadFactory&& pre)
     {
-      transposedOp_.setQuadFactory(std::forward<PreQuadFactory>(pre));
+      transposedOp_.setQuadFactory(FWD(pre));
     }
 
   private:
@@ -210,9 +210,8 @@ namespace AMDiS
   template <class Tag, class Expr, class... QuadratureArgs>
   auto makeOperator(Tag tag, Expr&& expr, QuadratureArgs&&... args)
   {
-    auto pqf = makePreQuadratureFactory(std::forward<QuadratureArgs>(args)...);
-    using PreGridFctOp = PreGridFunctionOperator<Tag, std::decay_t<Expr>, decltype(pqf)>;
-    return PreGridFctOp{tag, std::forward<Expr>(expr), std::move(pqf)};
+    auto pqf = makePreQuadratureFactory(FWD(args)...);
+    return PreGridFunctionOperator<Tag, TYPEOF(expr), TYPEOF(pqf)>{tag, FWD(expr), std::move(pqf)};
   }
 
   /** @} **/
@@ -238,9 +237,8 @@ namespace AMDiS
   template <class Context, class Tag, class GF, class QF>
   auto makeGridFunctionOperator(Tag tag, GF&& gf, QF&& qf)
   {
-    using GridFctOp = GridFunctionOperator<Tag, Context, std::decay_t<GF>>;
-    GridFctOp gfo{tag, std::forward<GF>(gf)};
-    gfo.setQuadFactory(std::forward<QF>(qf));
+    GridFunctionOperator<Tag, Context, TYPEOF(gf)> gfo{tag, FWD(gf)};
+    gfo.setQuadFactory(FWD(qf));
     return gfo;
   }
 
diff --git a/src/amdis/Integrate.hpp b/src/amdis/Integrate.hpp
index 08d527a11f78e2228be58de6e3f4ad63dac08020..2a9522689838189068d18e4d57af1a0ce39b706c 100644
--- a/src/amdis/Integrate.hpp
+++ b/src/amdis/Integrate.hpp
@@ -11,9 +11,9 @@ namespace AMDiS
     template <class GF, class GridView, class QuadProvider>
     auto integrateImpl(GF&& gf, GridView const& gridView, QuadProvider makeQuad)
     {
-      auto localFct = localFunction(std::forward<GF>(gf));
+      auto localFct = localFunction(FWD(gf));
 
-      using GridFct = std::decay_t<GF>;
+      using GridFct = remove_cvref_t<GF>;
       using Range = typename GridFct::Range;
       Range result(0);
 
@@ -34,7 +34,7 @@ namespace AMDiS
     template <class GF, class GridView, class QuadProvider>
     auto integrateImpl(GF&& gf, GridView const& gv, QuadProvider makeQuad, std::true_type)
     {
-      return integrateImpl(std::forward<GF>(gf), gv, makeQuad);
+      return integrateImpl(FWD(gf), gv, makeQuad);
     }
 
     template <class GF, class GV, class QP>
@@ -55,10 +55,10 @@ namespace AMDiS
   template <class Expr, class GridView>
   auto integrate(Expr&& expr, GridView const& gridView)
   {
-    auto&& gridFct = makeGridFunction(std::forward<Expr>(expr), gridView);
+    auto&& gridFct = makeGridFunction(FWD(expr), gridView);
 
     // test whether the gridFct model `Concepts::HasLocalFunctionOrder`
-    using GF = std::decay_t<decltype(gridFct)>;
+    using GF = TYPEOF(gridFct);
     static const bool expr_has_order = Concepts::HasLocalFunctionOrder<GF>;
     static_assert(expr_has_order,
       "Polynomial degree of expression can not be deduced. You need to provide an explicit value for the quadrature degree or a quadrature rule in `integrate()`.");
@@ -66,8 +66,7 @@ namespace AMDiS
     using Rules = Dune::QuadratureRules<typename GridView::ctype, GridView::dimension>;
     auto makeQuad = [](auto&& t, auto&& lf) { return Rules::rule(t, order(lf)); };
 
-    return Impl::integrateImpl(std::forward<decltype(gridFct)>(gridFct), gridView, makeQuad,
-      std::integral_constant<bool,expr_has_order>{});
+    return Impl::integrateImpl(FWD(gridFct), gridView, makeQuad, bool_<expr_has_order>);
   }
 
 
@@ -83,9 +82,8 @@ namespace AMDiS
     class QuadratureRule = Dune::QuadratureRule<typename GridView::ctype, GridView::dimension>>
   auto integrate(Expr&& expr, GridView const& gridView, QuadratureRule const& quad)
   {
-    auto&& gridFct = makeGridFunction(std::forward<Expr>(expr), gridView);
-    return Impl::integrateImpl(std::forward<decltype(gridFct)>(gridFct), gridView,
-      [&](auto&&, auto&&) { return quad; });
+    auto&& gridFct = makeGridFunction(FWD(expr), gridView);
+    return Impl::integrateImpl(FWD(gridFct), gridView, [&](auto&&, auto&&) { return quad; });
   }
 
 
@@ -102,8 +100,8 @@ namespace AMDiS
   {
     using Rules = Dune::QuadratureRules<typename GridView::ctype, GridView::dimension>;
 
-    auto&& gridFct = makeGridFunction(std::forward<Expr>(expr), gridView);
-    return Impl::integrateImpl(std::forward<decltype(gridFct)>(gridFct), gridView,
+    auto&& gridFct = makeGridFunction(FWD(expr), gridView);
+    return Impl::integrateImpl(FWD(gridFct), gridView,
       [&](auto const& type, auto&&) { return Rules::rule(type, degree, qt); });
   }
 
diff --git a/src/amdis/Marker.hpp b/src/amdis/Marker.hpp
index 83c62e522d74910aabe526ae8b70aca0e38c6020..48f5ccd24f18f04c46551d27a3bf202f01f9c5fa 100644
--- a/src/amdis/Marker.hpp
+++ b/src/amdis/Marker.hpp
@@ -8,6 +8,7 @@
 #include <dune/grid/common/grid.hh>
 
 #include <amdis/common/ConceptsBase.hpp>
+#include <amdis/common/TypeTraits.hpp>
 
 #include <amdis/gridfunctions/GridFunctionConcepts.hpp>
 
@@ -382,7 +383,7 @@ namespace AMDiS
     template <class GF>
     GridFunctionMarker(std::string const& name, std::shared_ptr<Grid> const& grid, GF&& gf)
       : Super{name, grid}
-      , gridFct_{makeGridFunction(std::forward<GF>(gf), grid->leafGridView())}
+      , gridFct_{makeGridFunction(FWD(gf), grid->leafGridView())}
     {}
 
     /// \brief Implementation of \ref Marker::markElement. Does nothing since marking is
@@ -402,11 +403,10 @@ namespace AMDiS
 
 #if DUNE_HAVE_CXX_CLASS_TEMPLATE_ARGUMENT_DEDUCTION
   // Deduction guide for GridFunctionMarker class
-  template <class Grid, class PreGridFct>
-  GridFunctionMarker(std::string const& name, std::shared_ptr<Grid> const& grid,
-                     PreGridFct&& preGridFct)
+  template <class Grid, class GF>
+  GridFunctionMarker(std::string const& name, std::shared_ptr<Grid> const& grid, GF&& gf)
     -> GridFunctionMarker<Grid,
-          std::decay_t<decltype(makeGridFunction(std::forward<PreGridFct>(preGridFct), grid->leafGridView()))>>;
+          TYPEOF( makeGridFunction(FWD(gf), grid->leafGridView()) )>;
 #endif
 
   // Generator function for GridFunctionMarker class
@@ -414,9 +414,8 @@ namespace AMDiS
   auto makeGridFunctionMarker(std::string const& name, std::shared_ptr<Grid> const& grid,
                               PreGridFct&& preGridFct)
   {
-    auto gridFct = makeGridFunction(std::forward<PreGridFct>(preGridFct), grid->leafGridView());
-    using GridFct = decltype(gridFct);
-    return GridFunctionMarker<Grid,GridFct>{name, grid, gridFct};
+    auto gridFct = makeGridFunction(FWD(preGridFct), grid->leafGridView());
+    return GridFunctionMarker<Grid,TYPEOF(gridFct)>{name, grid, std::move(gridFct)};
   }
 
 } // end namespace AMDiS
diff --git a/src/amdis/OperatorList.hpp b/src/amdis/OperatorList.hpp
index b0807c857922ef0c4ecae214e160b6c7a038ef13..35adb2c99e0960f9000f46b44b2835f9714c45b2 100644
--- a/src/amdis/OperatorList.hpp
+++ b/src/amdis/OperatorList.hpp
@@ -76,19 +76,19 @@ namespace AMDiS
       template <class Op>
       void push(tag::element_operator<Element>, Op&& op)
       {
-        element_.emplace_back(std::forward<Op>(op));
+        element_.emplace_back(FWD(op));
       }
 
       template <class Op>
       void push(tag::intersection_operator<Intersection>, Op&& op)
       {
-        intersection_.emplace_back(std::forward<Op>(op));
+        intersection_.emplace_back(FWD(op));
       }
 
       template <class Op>
       void push(tag::boundary_operator<Intersection> b, Op&& op)
       {
-        boundary_.push_back({std::forward<Op>(op), b});
+        boundary_.push_back({FWD(op), b});
       }
 
 
diff --git a/src/amdis/Output.hpp b/src/amdis/Output.hpp
index af4d5ff3a222459edab1920832e6dddb39e71dc3..91264e57eb44d532395bb0a7cfb227f27d408c07 100644
--- a/src/amdis/Output.hpp
+++ b/src/amdis/Output.hpp
@@ -22,6 +22,8 @@
 #include <fmt/core.h>
 #include <fmt/ostream.h>
 
+#include <amdis/common/TypeTraits.hpp>
+
 /**
  * \def AMDIS_ENABLE_MSG_DBG
  * \brief The preprocessor constant enables the functions \ref AMDiS::MSG_DBG
@@ -66,12 +68,12 @@ namespace AMDiS
       MPI_Comm_size(MPI_COMM_WORLD, &num_ranks);
       if (num_ranks > 1 && rank == 0) {
         out << "[0] ";
-        fmt::print(out, std::forward<Args>(args)...);
+        fmt::print(out, FWD(args)...);
       } else if (num_ranks == 1) {
-        fmt::print(out, std::forward<Args>(args)...);
+        fmt::print(out, FWD(args)...);
       }
 #else
-      fmt::print(out, std::forward<Args>(args)...);
+      fmt::print(out, FWD(args)...);
 #endif
       return out;
     }
@@ -89,7 +91,7 @@ namespace AMDiS
   template <class... Args>
   void msg(Args&&... args)
   {
-    Impl::msg(std::cout, std::forward<Args>(args)...) << std::endl;
+    Impl::msg(std::cout, FWD(args)...) << std::endl;
   }
 
 
@@ -103,7 +105,7 @@ namespace AMDiS
   template <class... Args>
   void msg_(Args&&... args)
   {
-    Impl::msg(std::cout, std::forward<Args>(args)...);
+    Impl::msg(std::cout, FWD(args)...);
   }
 
 
@@ -117,14 +119,14 @@ namespace AMDiS
   void error_exit(Args&&... args)
   {
 #ifdef AMDIS_NO_THROW
-    Impl::msg(std::cerr << "ERROR: ", std::forward<Args>(args)...) << std::endl;
+    Impl::msg(std::cerr << "ERROR: ", FWD(args)...) << std::endl;
     #ifndef NDEBUG
       assert(false);
     #else
       std::exit(EXIT_FAILURE);
     #endif
 #else
-    throw std::runtime_error( std::string("ERROR: ") + fmt::format(std::forward<Args>(args)...));
+    throw std::runtime_error( std::string("ERROR: ") + fmt::format(FWD(args)...));
 #endif
   }
 
@@ -141,14 +143,14 @@ namespace AMDiS
   template <class... Args>
   void test_exit(bool condition, Args&&... args)
   {
-    if (!condition) { error_exit(std::forward<Args>(args)...); }
+    if (!condition) { error_exit(FWD(args)...); }
   }
 
 
   template <class... Args>
   void warning(Args&&... args)
   {
-    Impl::msg(std::cout << "WARNING: ", std::forward<Args>(args)...) << std::endl;
+    Impl::msg(std::cout << "WARNING: ", FWD(args)...) << std::endl;
   }
 
 
@@ -161,7 +163,7 @@ namespace AMDiS
   template <class... Args>
   void test_warning(bool condition, Args&&... args)
   {
-    if (!condition) { warning(std::forward<Args>(args)...); }
+    if (!condition) { warning(FWD(args)...); }
   }
 
 
@@ -172,7 +174,7 @@ namespace AMDiS
    * \ref AMDIS_ENABLE_MSG_DBG is set to 1, otherwise the function is empty.
    **/
   template <class... Args>
-  void msg_dbg(Args&&... args) { msg(std::forward<Args>(args)...); }
+  void msg_dbg(Args&&... args) { msg(FWD(args)...); }
 
 
   /// \brief call assert_msg, in debug mode only
@@ -183,7 +185,7 @@ namespace AMDiS
   template <class... Args>
   void test_exit_dbg(bool condition, Args&&... args)
   {
-    test_exit(condition, std::forward<Args>(args)...);
+    test_exit(condition, FWD(args)...);
   }
 #else
   template <class... Args>
diff --git a/src/amdis/PeriodicBC.hpp b/src/amdis/PeriodicBC.hpp
index 23f4fb374ebb28fd35479d2224ab0ad17da3f2ef..65541856963d02c5d426a4c0560f8e4d91f66bbd 100644
--- a/src/amdis/PeriodicBC.hpp
+++ b/src/amdis/PeriodicBC.hpp
@@ -54,7 +54,7 @@ namespace AMDiS
   public:
     template <class BM>
     PeriodicBC(BM&& boundaryManager, BoundaryType id, FaceTrafo faceTrafo)
-      : Super(std::forward<BM>(boundaryManager), id)
+      : Super(FWD(boundaryManager), id)
       , faceTrafo_(std::move(faceTrafo))
     {}
 
diff --git a/src/amdis/PeriodicBC.inc.hpp b/src/amdis/PeriodicBC.inc.hpp
index ea08e9ed52e0e1eb281fb5d62e6f3d573e19fbcf..a0c03627349d0686ccc042fd3daddfd5745400f1 100644
--- a/src/amdis/PeriodicBC.inc.hpp
+++ b/src/amdis/PeriodicBC.inc.hpp
@@ -202,7 +202,7 @@ coords(Node const& tree, std::vector<std::size_t> const& localIndices) const
     auto geometry = node.element().geometry();
 
     auto const& localInterpol = node.finiteElement().localInterpolation();
-    using FiniteElement = std::decay_t<decltype(node.finiteElement())>;
+    using FiniteElement = TYPEOF(node.finiteElement());
     using DomainType = typename FiniteElement::Traits::LocalBasisType::Traits::DomainType;
     using RangeType = typename FiniteElement::Traits::LocalBasisType::Traits::RangeType;
 
diff --git a/src/amdis/common/Apply.hpp b/src/amdis/common/Apply.hpp
index 05bab973c292df65934fb2f3e4237032d93684b8..7cade13417b9106709376ac7d98b496a76aadb11 100644
--- a/src/amdis/common/Apply.hpp
+++ b/src/amdis/common/Apply.hpp
@@ -5,6 +5,7 @@
 #include <utility>
 
 #include <amdis/common/Mpl.hpp>
+#include <amdis/common/TypeTraits.hpp>
 
 namespace AMDiS
 {
@@ -15,7 +16,7 @@ namespace AMDiS
       template <class F, class Tuple, std::size_t... I>
       constexpr decltype(auto) apply_impl(F&& f, Tuple&& t, std::index_sequence<I...>)
       {
-        return f(std::get<I>(std::forward<Tuple>(t))...);
+        return f(std::get<I>(FWD(t))...);
       }
 
       template <class F, std::size_t I0, std::size_t... I>
@@ -28,31 +29,27 @@ namespace AMDiS
     template <class F, class Tuple>
     constexpr decltype(auto) apply(F&& f, Tuple&& t)
     {
-        return Impl_::apply_impl(
-            std::forward<F>(f), std::forward<Tuple>(t),
+        return Impl_::apply_impl(FWD(f), FWD(t),
             std::make_index_sequence<std::tuple_size<std::remove_reference_t<Tuple>>::value>{});
     }
 
     template <class F, class... Args>
     constexpr decltype(auto) apply_variadic(F&& f, Args&&... args)
     {
-        return apply(std::forward<F>(f), std::forward_as_tuple(args...));
+        return apply(FWD(f), std::forward_as_tuple(args...));
     }
 
     template <class F, std::size_t N>
     constexpr decltype(auto) apply_indices(F&& f, index_t<N>)
     {
-      return Impl_::apply_indices_impl(
-          std::forward<F>(f),
-          index_t<0>{},
+      return Impl_::apply_indices_impl(FWD(f), index_t<0>{},
           std::make_index_sequence<N>{});
     }
 
     template <class F, std::size_t I0, std::size_t I1>
     constexpr decltype(auto) apply_indices(F&& f, index_t<I0>, index_t<I1>)
     {
-      return Impl_::apply_indices_impl(
-          std::forward<F>(f), index_t<I0>{},
+      return Impl_::apply_indices_impl(FWD(f), index_t<I0>{},
           std::make_index_sequence<I1-I0>{});
     }
   }
diff --git a/src/amdis/common/Concepts.hpp b/src/amdis/common/Concepts.hpp
index ed851525ac7b16cdb7201a2354d5333dd0cb8d12..d17060df9a384a82fbee31f18e9f1b5bc0327853 100644
--- a/src/amdis/common/Concepts.hpp
+++ b/src/amdis/common/Concepts.hpp
@@ -20,7 +20,7 @@ namespace AMDiS
   {
     template <class A, class B>
     struct IsSimilar
-      : std::is_same<std::decay_t<A>, std::decay_t<B>> {};
+      : std::is_same<remove_cvref_t<A>, remove_cvref_t<B>> {};
 
     template <class A, class B>
     struct IsSimilar<Types<A>, Types<B>>
@@ -52,7 +52,7 @@ namespace AMDiS
       struct Callable
       {
         template <class F, class... Args>
-        auto requires_(F&& f, Args&&... args) -> decltype( f(std::forward<Args>(args)...));
+        auto requires_(F&& f, Args&&... args) -> decltype(f(FWD(args)...));
       };
 
       // idx[0]
diff --git a/src/amdis/common/ConcurrentCache.hpp b/src/amdis/common/ConcurrentCache.hpp
index 8e84f7b5fa350768f17865955fa737a3eac26458..eb28a417f46bf9199bd1c9df59ab4b7fe9d91b7e 100644
--- a/src/amdis/common/ConcurrentCache.hpp
+++ b/src/amdis/common/ConcurrentCache.hpp
@@ -78,8 +78,7 @@ namespace AMDiS
     template <class F, class... Args>
     data_type const& get_or_init(key_type const& key, F&& f, Args&&... args) const
     {
-      return impl(std::is_default_constructible<data_type>{},
-        key, std::forward<F>(f), std::forward<Args>(args)...);
+      return impl(std::is_default_constructible<data_type>{}, key, FWD(f), FWD(args)...);
     }
 
   private:
@@ -90,7 +89,7 @@ namespace AMDiS
       data_type empty;
       auto it = cachedData_.emplace(key, std::move(empty));
       if (it.second) {
-        data_type data = f(key, std::forward<Args>(args)...);
+        data_type data = f(key, FWD(args)...);
         it.first->second = std::move(data);
       }
       return it.first->second;
@@ -104,7 +103,7 @@ namespace AMDiS
       if (it != cachedData_.end())
         return it->second;
       else {
-        data_type data = f(key, std::forward<Args>(args)...);
+        data_type data = f(key, FWD(args)...);
         auto it = cachedData_.emplace(key, std::move(data));
         return it.first->second;
       }
@@ -125,8 +124,7 @@ namespace AMDiS
     template <class F, class... Args>
     static data_type const& get_or_init(key_type const& key, F&& f, Args&&... args)
     {
-      return impl(std::is_default_constructible<data_type>{},
-        key, std::forward<F>(f), std::forward<Args>(args)...);
+      return impl(std::is_default_constructible<data_type>{}, key, FWD(f), FWD(args)...);
     }
 
   private:
@@ -140,7 +138,7 @@ namespace AMDiS
       data_type empty;
       auto it = cached_data.emplace(key, std::move(empty));
       if (it.second) {
-        data_type data = f(key, std::forward<Args>(args)...);
+        data_type data = f(key, FWD(args)...);
         it.first->second = std::move(data);
       }
       return it.first->second;
@@ -157,7 +155,7 @@ namespace AMDiS
       if (it != cached_data.end())
         return it->second;
       else {
-        data_type data = f(key, std::forward<Args>(args)...);
+        data_type data = f(key, FWD(args)...);
         auto it = cached_data.emplace(key, std::move(data));
         return it.first->second;
       }
@@ -192,7 +190,7 @@ namespace AMDiS
         return it->second;
       else {
         read_lock.unlock();
-        data_type data = f(key, std::forward<Args>(args)...);
+        data_type data = f(key, FWD(args)...);
         std::unique_lock<mutex_type> write_lock(access_mutex);
         auto new_it = cached_data.emplace(key, std::move(data));
         return new_it.first->second;
@@ -224,7 +222,7 @@ namespace AMDiS
       static_assert(Dune::Std::is_callable<F(key_type, Args...), data_type>::value,
         "Functor F must have the signature data_type(key_type, Args...)");
 
-      return ConcurrentCache::get_or_init(key, std::forward<F>(f), std::forward<Args>(args)...);
+      return ConcurrentCache::get_or_init(key, FWD(f), FWD(args)...);
     }
   };
 
diff --git a/src/amdis/common/FieldMatVec.hpp b/src/amdis/common/FieldMatVec.hpp
index 165e98d6eb97e2871c6f993b3837609262eb0e64..8c4aeb876ec911b7fb7a10de7588951d24a34e9d 100644
--- a/src/amdis/common/FieldMatVec.hpp
+++ b/src/amdis/common/FieldMatVec.hpp
@@ -7,6 +7,8 @@
 #include <dune/common/fvector.hh>
 #include <dune/common/typetraits.hh>
 
+#include <amdis/common/TypeTraits.hpp>
+
 namespace std
 {
   template <class T, int N>
@@ -82,7 +84,7 @@ namespace Dune
     template <class T>
     decltype(auto) simplify(T&& t)
     {
-      return std::forward<T>(t);
+      return FWD(t);
     }
 
     template <class T>
diff --git a/src/amdis/common/FieldMatVec.inc.hpp b/src/amdis/common/FieldMatVec.inc.hpp
index 40d8dbe696104d35966b265267e269f7c52fa626..4644778c2ab358493e94ceffcdb4a57ca5383bee 100644
--- a/src/amdis/common/FieldMatVec.inc.hpp
+++ b/src/amdis/common/FieldMatVec.inc.hpp
@@ -305,7 +305,7 @@ T distance(FieldVector<T, N> const& lhs, FieldVector<T, N> const& rhs)
 template <class T, class S, int N, int M, int K>
 auto outer(FieldMatrix<T,N,K> const& vec1, FieldMatrix<S,M,K> const& vec2)
 {
-  using result_type = FieldMatrix<decltype( std::declval<T>() * std::declval<S>() ), N, M>;
+  using result_type = FieldMatrix<TYPEOF( std::declval<T>() * std::declval<S>() ), N, M>;
   result_type mat;
   for (int i = 0; i < N; ++i)
     for (int j = 0; j < M; ++j)
diff --git a/src/amdis/common/MultiTypeMatrix.hpp b/src/amdis/common/MultiTypeMatrix.hpp
index 2a512bda65ae25d5069e285e46511cca2c8fbfbe..392005aefa4c8f896b57b28a97ace714cf4c6f85 100644
--- a/src/amdis/common/MultiTypeMatrix.hpp
+++ b/src/amdis/common/MultiTypeMatrix.hpp
@@ -56,7 +56,7 @@ namespace AMDiS
     template <class... Rows_,
       REQUIRES( Concepts::Similar<Types<Rows...>, Types<Rows_...>> )>
     MultiTypeMatrix(Rows_&&... rows)
-      : Super(std::forward<Rows_>(rows)...)
+      : Super(FWD(rows)...)
     {}
 
     /// Default construction of tuple of FieldVectors
diff --git a/src/amdis/common/MultiTypeVector.hpp b/src/amdis/common/MultiTypeVector.hpp
index bfe4a24f058e61e6eaa958aad289e4bb08e4142f..1f3e38f57a54795f0cd3deb1ccf6a85846ff8e3f 100644
--- a/src/amdis/common/MultiTypeVector.hpp
+++ b/src/amdis/common/MultiTypeVector.hpp
@@ -49,7 +49,7 @@ namespace AMDiS
     template <class... FV_,
       REQUIRES( Concepts::Similar<Types<FV...>, Types<FV_...>> )>
     MultiTypeVector(FV_&&... fv)
-      : Super(std::forward<FV_>(fv)...)
+      : Super(FWD(fv)...)
     {}
 
     /// Default construction of tuple of FieldVectors
diff --git a/src/amdis/common/StaticSize.hpp b/src/amdis/common/StaticSize.hpp
index 81d5d48c1ea1422ad7cee5f01fed4317e9e17fad..d1b399e15f4c750b4e2e8c7421d74bc397fdb5ec 100644
--- a/src/amdis/common/StaticSize.hpp
+++ b/src/amdis/common/StaticSize.hpp
@@ -79,10 +79,10 @@ namespace AMDiS
 
   /// Get the number of elements in a tuple / pair / array / ...
   template <class T>
-  constexpr std::size_t Size_v = Impl::SizeImpl<std::decay_t<T>>::value;
+  constexpr std::size_t Size_v = Impl::SizeImpl<remove_cvref_t<T>>::value;
 
   template <class T>
-  using Size_t = Impl::SizeImpl<std::decay_t<T>>;
+  using Size_t = Impl::SizeImpl<remove_cvref_t<T>>;
 
 
   namespace Impl
@@ -111,10 +111,10 @@ namespace AMDiS
 
   /// Get the number of rows in a fixed-size matrix
   template <class T>
-  constexpr std::size_t Rows_v = Impl::RowsImpl<std::decay_t<T>>::value;
+  constexpr std::size_t Rows_v = Impl::RowsImpl<remove_cvref_t<T>>::value;
 
   template <class T>
-  using Rows_t = Impl::RowsImpl<std::decay_t<T>>;
+  using Rows_t = Impl::RowsImpl<remove_cvref_t<T>>;
 
 
   namespace Impl
@@ -143,9 +143,9 @@ namespace AMDiS
 
   /// Get the number of columns in a fixed-size matrix
   template <class T>
-  constexpr std::size_t Cols_v = Impl::ColsImpl<std::decay_t<T>>::value;
+  constexpr std::size_t Cols_v = Impl::ColsImpl<remove_cvref_t<T>>::value;
 
   template <class T>
-  using Cols_t = Impl::ColsImpl<std::decay_t<T>>;
+  using Cols_t = Impl::ColsImpl<remove_cvref_t<T>>;
 
 } // end namespace AMDiS
diff --git a/src/amdis/common/Transposed.hpp b/src/amdis/common/Transposed.hpp
index 4778e95f956c1ee1635e7d7ab18a5271a47faed5..38920b9665f73ce240b180505a604bb68bc63f1b 100644
--- a/src/amdis/common/Transposed.hpp
+++ b/src/amdis/common/Transposed.hpp
@@ -8,7 +8,7 @@ namespace AMDiS
   template <class Matrix>
   class TransposedMatrix
   {
-    using RawMatrix = std::decay_t<Matrix>;
+    using RawMatrix = remove_cvref_t<Matrix>;
 
   public:
     using size_type = typename RawMatrix::size_type;
@@ -40,7 +40,7 @@ namespace AMDiS
   public:
     template <class M>
     TransposedMatrix(M&& matrix)
-      : matrix_(std::forward<M>(matrix))
+      : matrix_(FWD(matrix))
     {}
 
     ConstRowProxy operator[](size_type row) const
@@ -73,7 +73,7 @@ namespace AMDiS
   auto transposed(Matrix&& matrix)
   {
     using M = std::remove_reference_t<Matrix>;
-    return TransposedMatrix<M>{std::forward<Matrix>(matrix)};
+    return TransposedMatrix<M>{FWD(matrix)};
   }
 
 } // end namespace AMDiS
diff --git a/src/amdis/common/TypeTraits.hpp b/src/amdis/common/TypeTraits.hpp
index 4739771297b15867f290f8bc2993973925899c23..721ec6f035b50dc43446919ea1d9b4d3ab538924 100644
--- a/src/amdis/common/TypeTraits.hpp
+++ b/src/amdis/common/TypeTraits.hpp
@@ -12,24 +12,52 @@
 
 namespace AMDiS
 {
+  /// \brief Remove cv and ref qualifiers of type T.
+  /**
+   * If the type T is a reference type, provides the member typedef type which
+   * is the type referred to by T with its topmost cv-qualifiers removed.
+   * Otherwise type is T with its topmost cv-qualifiers removed.
+   *
+   * Note: This is a backport of c++20 std::remove_cvref
+   **/
+  template< class T >
+  struct remove_cvref
+  {
+    using type = std::remove_cv_t<std::remove_reference_t<T>>;
+  };
+
+  /// Helper alias template for \ref remove_cvref
+  template< class T >
+  using remove_cvref_t = typename remove_cvref<T>::type;
+
   namespace Impl
   {
     template <class T>
     struct UnderlyingType
     {
-      using type = T;
+      using type = remove_cvref_t<T>;
     };
 
     template <class T>
     struct UnderlyingType<std::reference_wrapper<T>>
     {
-      using type = T;
+      using type = remove_cvref_t<T>;
     };
   }
 
   template <class T>
   using Underlying_t = typename Impl::UnderlyingType<T>::type;
 
+
+  /// Macro for forwarding universal references to obj
+  #define FWD(obj) std::forward<decltype(obj)>(obj)
+
+  /// A decay version of decltype, similar to GCCs __typeof__
+  #define TYPEOF(...) AMDiS::remove_cvref_t<decltype(__VA_ARGS__)>
+
+  /// Extract the static value of an integral_constant variable
+  #define VALUE(...) TYPEOF(__VA_ARGS__)::value
+
   // ---------------------------------------------------------------------------
 
   /// A variadic type list
@@ -37,7 +65,7 @@ namespace AMDiS
   struct Types {};
 
   template <class... Ts>
-  using Types_t = Types<std::decay_t<Ts>...>;
+  using Types_t = Types<remove_cvref_t<Ts>...>;
 
 
   /// Alias that indicates ownership of resources
@@ -49,7 +77,7 @@ namespace AMDiS
   template <class Obj>
   auto makeUniquePtr(Obj&& obj)
   {
-    return std::make_unique<std::decay_t<Obj>>(std::forward<Obj>(obj));
+    return std::make_unique<TYPEOF(obj)>(FWD(obj));
   }
 
 } // end namespace AMDiS
diff --git a/src/amdis/common/ValueCategory.hpp b/src/amdis/common/ValueCategory.hpp
index 3c1b61c3fafce2672954b42680452314067328e3..71d72db14c371e0629d7070c13d5425e84128f87 100644
--- a/src/amdis/common/ValueCategory.hpp
+++ b/src/amdis/common/ValueCategory.hpp
@@ -18,7 +18,7 @@ namespace AMDiS
   };
 
   template <class T>
-  using ValueCategory_t = typename ValueCategory<std::decay_t<T>>::type;
+  using ValueCategory_t = typename ValueCategory<remove_cvref_t<T>>::type;
 
   template <class T>
   struct ValueCategory<T, std::enable_if_t< std::is_arithmetic<T>::value >>
diff --git a/src/amdis/gridfunctions/AnalyticGridFunction.hpp b/src/amdis/gridfunctions/AnalyticGridFunction.hpp
index 533038206715299e77cc5d75b789a820aaac3c39..c0994d4f947187c9bba1fd3d8224908172c8466b 100644
--- a/src/amdis/gridfunctions/AnalyticGridFunction.hpp
+++ b/src/amdis/gridfunctions/AnalyticGridFunction.hpp
@@ -129,7 +129,7 @@ namespace AMDiS
   public:
     using EntitySet = Dune::Functions::GridViewEntitySet<GridView, 0>;
     using Domain = typename EntitySet::GlobalCoordinate;
-    using Range = std::decay_t<std::result_of_t<Function(Domain)>>;
+    using Range = remove_cvref_t<std::result_of_t<Function(Domain)>>;
 
     enum { hasDerivative = true };
 
diff --git a/src/amdis/gridfunctions/DOFVectorView.hpp b/src/amdis/gridfunctions/DOFVectorView.hpp
index 55f0bf74ecd8cc6679aaab03d16bdc3c83a1bbc4..f95677a960a72583a1807c9e38efae57feee6a27 100644
--- a/src/amdis/gridfunctions/DOFVectorView.hpp
+++ b/src/amdis/gridfunctions/DOFVectorView.hpp
@@ -44,10 +44,9 @@ namespace AMDiS
       auto const& basis = this->basis();
       auto const& treePath = this->treePath();
 
-      auto&& gridFct = makeGridFunction(std::forward<Expr>(expr), basis.gridView());
+      auto&& gridFct = makeGridFunction(FWD(expr), basis.gridView());
 
-      Dune::Functions::interpolate(basis, treePath, coefficients(),
-        std::forward<decltype(gridFct)>(gridFct));
+      Dune::Functions::interpolate(basis, treePath, coefficients(), FWD(gridFct));
     }
 
     /// \brief Interpolation of GridFunction to DOFVector
@@ -66,7 +65,7 @@ namespace AMDiS
       // create temporary copy of data
       DOFVector<GB,VT> tmp(coefficients());
       Self tmpView{tmp, this->treePath()};
-      tmpView.interpolate_noalias(std::forward<Expr>(expr));
+      tmpView.interpolate_noalias(FWD(expr));
 
       // move data from temporary vector into stored DOFVector
       coefficients().vector() = std::move(tmp.vector());
diff --git a/src/amdis/gridfunctions/DerivativeGridFunction.hpp b/src/amdis/gridfunctions/DerivativeGridFunction.hpp
index f1b2abeb9e47cfb8ac379ed5e0b8e9f10d36714a..19693c8dff4051a82c5d561b16fb03b513e54e66 100644
--- a/src/amdis/gridfunctions/DerivativeGridFunction.hpp
+++ b/src/amdis/gridfunctions/DerivativeGridFunction.hpp
@@ -29,7 +29,7 @@ namespace AMDiS
     using GridFctDomain = typename GridFunction::Domain;
     using RawSignature = typename Dune::Functions::SignatureTraits<GridFctRange(GridFctDomain)>::RawSignature;
     using DerivativeTraits = Dune::Functions::DefaultDerivativeTraits<RawSignature>;
-    using LocalFunction = std::decay_t<decltype(derivative(localFunction(std::declval<GridFunction>())))>;
+    using LocalFunction = TYPEOF( derivative(localFunction(std::declval<GridFunction>())) ) ;
 
     enum { hasDerivative = false };
 
diff --git a/src/amdis/gridfunctions/DiscreteFunction.inc.hpp b/src/amdis/gridfunctions/DiscreteFunction.inc.hpp
index 069e67c610ca5e9fea508daad154b62e5542fd1d..52c47b3ef8d7f88f3dc358b38dbae365066481f4 100644
--- a/src/amdis/gridfunctions/DiscreteFunction.inc.hpp
+++ b/src/amdis/gridfunctions/DiscreteFunction.inc.hpp
@@ -152,8 +152,7 @@ LocalFunction::operator()(Domain const& x) const
     auto&& fe = node.finiteElement();
     auto&& localBasis = fe.localBasis();
 
-    using Node = std::decay_t<decltype(node)>;
-    NodeCache<Node> localBasisCache(localBasis);
+    NodeCache<TYPEOF(node)> localBasisCache(localBasis);
     auto const& shapeFunctionValues = localBasisCache.evaluateFunction(localView_.element().type(),x);
 
     // Get range entry associated to this node
@@ -204,8 +203,7 @@ GradientLocalFunction::operator()(Domain const& x) const
     auto&& fe = node.finiteElement();
     auto&& localBasis = fe.localBasis();
 
-    using Node = std::decay_t<decltype(node)>;
-    NodeCache<Node> localBasisCache(localBasis);
+    NodeCache<TYPEOF(node)> localBasisCache(localBasis);
     auto const& referenceGradients = localBasisCache.evaluateJacobian(localView_.element().type(),x);
 
     // The transposed inverse Jacobian of the map from the reference element to the element
diff --git a/src/amdis/gridfunctions/FunctorGridFunction.hpp b/src/amdis/gridfunctions/FunctorGridFunction.hpp
index 99688cf23908e5e092400f35a3c38d89ae64d3c2..628cc050116118ec556e159838049c13414e0c39 100644
--- a/src/amdis/gridfunctions/FunctorGridFunction.hpp
+++ b/src/amdis/gridfunctions/FunctorGridFunction.hpp
@@ -67,7 +67,7 @@ namespace AMDiS
     template <class... GridFcts>
     FunctorLocalFunction(Functor const& fct, GridFcts&&... gridFcts)
       : fct_{fct}
-      , localFcts_{std::forward<GridFcts>(gridFcts)...}
+      , localFcts_{FWD(gridFcts)...}
     {}
 
     /// Calls \ref bind for all localFunctions
@@ -136,7 +136,7 @@ namespace AMDiS
       }, lf.localFcts());
 
       using std::get;
-      auto const& lgfs_i = *get<decltype(_i)::value>(lf.localFcts());
+      auto const& lgfs_i = *get<VALUE(_i)>(lf.localFcts());
       return makeFunctorGridFunction(Operation::Multiplies{}, di_f, derivative(lgfs_i));
     };
 
@@ -203,9 +203,9 @@ namespace AMDiS
 
   private:
     template <class GridFct>
-    using LocalFct = std::decay_t<decltype(localFunction(std::declval<GridFct>()))>;
+    using LocalFct = TYPEOF( localFunction(std::declval<GridFct>()) );
 
-    using RawRange = std::decay_t<Range>;
+    using RawRange = remove_cvref_t<Range>;
     using LocalDomain = typename EntitySet::LocalCoordinate;
 
   public:
@@ -215,7 +215,7 @@ namespace AMDiS
     template <class... GridFcts>
     explicit FunctorGridFunction(Functor const& fct, GridFcts&&... gridFcts)
       : fct_{fct}
-      , gridFcts_{std::forward<GridFcts>(gridFcts)...}
+      , gridFcts_{FWD(gridFcts)...}
     {}
 
     /// Applies the functor to the evaluated gridfunctions
@@ -288,7 +288,7 @@ namespace AMDiS
     template <class... PreGridFcts>
     explicit FunctorPreGridFunction(Functor const& fct, PreGridFcts&&... pgfs)
       : fct_{fct}
-      , preGridFcts_{std::forward<PreGridFcts>(pgfs)...}
+      , preGridFcts_{FWD(pgfs)...}
     {}
 
   private:
@@ -320,7 +320,7 @@ namespace AMDiS
   template <class Functor, class... PreGridFcts>
   auto invokeAtQP(Functor const& f, PreGridFcts&&... gridFcts)
   {
-    return FunctorPreGridFunction<Functor, std::decay_t<PreGridFcts>...>{f, std::forward<PreGridFcts>(gridFcts)...};
+    return FunctorPreGridFunction<Functor, TYPEOF(gridFcts)...>{f, FWD(gridFcts)...};
   }
 
 } // end namespace AMDiS
diff --git a/src/amdis/gridfunctions/GridFunctionConcepts.hpp b/src/amdis/gridfunctions/GridFunctionConcepts.hpp
index ac073736646f08d9a57b264f4693e6c58cded617..d9357bd025f5dbe6d574749bf7e34c1c44e195e5 100644
--- a/src/amdis/gridfunctions/GridFunctionConcepts.hpp
+++ b/src/amdis/gridfunctions/GridFunctionConcepts.hpp
@@ -120,8 +120,8 @@ namespace AMDiS
     /// can be converted to a GridFunction, or is already a GridFunction.
     template <class... GFs>
     constexpr bool AnyGridFunction =
-      any_of_v<GridFunction<std::decay_t<GFs>>...> ||
-      any_of_v<Traits::IsPreGridFunction<std::decay_t<GFs>>::value...>;
+      any_of_v<GridFunction<remove_cvref_t<GFs>>...> ||
+      any_of_v<Traits::IsPreGridFunction<remove_cvref_t<GFs>>::value...>;
 
     /** @} **/
 
diff --git a/src/amdis/gridfunctions/OperationsGridFunction.hpp b/src/amdis/gridfunctions/OperationsGridFunction.hpp
index 425d5d68d39247482e21a53143a8716e8e82391a..1800148565bf79f11c84db2cddf8bf3e8b51763b 100644
--- a/src/amdis/gridfunctions/OperationsGridFunction.hpp
+++ b/src/amdis/gridfunctions/OperationsGridFunction.hpp
@@ -20,7 +20,7 @@ namespace AMDiS
     REQUIRES(Concepts::AnyGridFunction<Lhs>)>
   auto operator-(Lhs&& lhs)
   {
-    return invokeAtQP(Operation::Negate{}, std::forward<Lhs>(lhs));
+    return invokeAtQP(Operation::Negate{}, FWD(lhs));
   }
 
   /// \brief Applies \ref Operation::Plus to GridFunctions. \relates FunctorGridFunction
@@ -28,7 +28,7 @@ namespace AMDiS
     REQUIRES(Concepts::AnyGridFunction<Lhs,Rhs>)>
   auto operator+(Lhs&& lhs, Rhs&& rhs)
   {
-    return invokeAtQP(Operation::Plus{}, std::forward<Lhs>(lhs), std::forward<Rhs>(rhs));
+    return invokeAtQP(Operation::Plus{}, FWD(lhs), FWD(rhs));
   }
 
   /// \brief Applies \ref Operation::Minus to GridFunctions. \relates FunctorGridFunction
@@ -36,7 +36,7 @@ namespace AMDiS
     REQUIRES(Concepts::AnyGridFunction<Lhs,Rhs>)>
   auto operator-(Lhs&& lhs, Rhs&& rhs)
   {
-    return invokeAtQP(Operation::Minus{}, std::forward<Lhs>(lhs), std::forward<Rhs>(rhs));
+    return invokeAtQP(Operation::Minus{}, FWD(lhs), FWD(rhs));
   }
 
   /// \brief Applies \ref Operation::Multiplies to GridFunctions. \relates FunctorGridFunction
@@ -44,7 +44,7 @@ namespace AMDiS
     REQUIRES(Concepts::AnyGridFunction<Lhs,Rhs>)>
   auto operator*(Lhs&& lhs, Rhs&& rhs)
   {
-    return invokeAtQP(Operation::Multiplies{}, std::forward<Lhs>(lhs), std::forward<Rhs>(rhs));
+    return invokeAtQP(Operation::Multiplies{}, FWD(lhs), FWD(rhs));
   }
 
   namespace Impl
@@ -53,14 +53,14 @@ namespace AMDiS
       REQUIRES(Concepts::ConstantToGridFunction<Value>)>
     auto divideAtQP(Lhs&& lhs, Value value)
     {
-      return invokeAtQP(Operation::Multiplies{}, std::forward<Lhs>(lhs), 1.0/value);
+      return invokeAtQP(Operation::Multiplies{}, FWD(lhs), 1.0/value);
     }
 
     template <class Lhs, class Rhs,
-      REQUIRES(not Concepts::ConstantToGridFunction<std::decay_t<Rhs>>)>
+      REQUIRES(not Concepts::ConstantToGridFunction<remove_cvref_t<Rhs>>)>
     auto divideAtQP(Lhs&& lhs, Rhs&& rhs)
     {
-      return invokeAtQP(Operation::Divides{}, std::forward<Lhs>(lhs), std::forward<Rhs>(rhs));
+      return invokeAtQP(Operation::Divides{}, FWD(lhs), FWD(rhs));
     }
   }
 
@@ -69,7 +69,7 @@ namespace AMDiS
     REQUIRES(Concepts::AnyGridFunction<Lhs,Rhs>)>
   auto operator/(Lhs&& lhs, Rhs&& rhs)
   {
-    return Impl::divideAtQP(std::forward<Lhs>(lhs), std::forward<Rhs>(rhs));
+    return Impl::divideAtQP(FWD(lhs), FWD(rhs));
   }
 
 
@@ -78,7 +78,7 @@ namespace AMDiS
     REQUIRES(Concepts::AnyGridFunction<Lhs,Rhs>)>
   auto max(Lhs&& lhs, Rhs&& rhs)
   {
-    return invokeAtQP(Operation::Max{}, std::forward<Lhs>(lhs), std::forward<Rhs>(rhs));
+    return invokeAtQP(Operation::Max{}, FWD(lhs), FWD(rhs));
   }
 
   /// \brief Applies \ref Operation::Min to GridFunctions. \relates FunctorGridFunction
@@ -86,7 +86,7 @@ namespace AMDiS
     REQUIRES(Concepts::AnyGridFunction<Lhs,Rhs>)>
   auto min(Lhs&& lhs, Rhs&& rhs)
   {
-    return invokeAtQP(Operation::Min{}, std::forward<Lhs>(lhs), std::forward<Rhs>(rhs));
+    return invokeAtQP(Operation::Min{}, FWD(lhs), FWD(rhs));
   }
 
   /// \brief Applies \ref Operation::AbsMax to GridFunctions. \relates FunctorGridFunction
@@ -94,7 +94,7 @@ namespace AMDiS
     REQUIRES(Concepts::AnyGridFunction<Lhs,Rhs>)>
   auto abs_max(Lhs&& lhs, Rhs&& rhs)
   {
-    return invokeAtQP(Operation::AbsMax{}, std::forward<Lhs>(lhs), std::forward<Rhs>(rhs));
+    return invokeAtQP(Operation::AbsMax{}, FWD(lhs), FWD(rhs));
   }
 
   /// \brief Applies \ref Operation::AbsMin to GridFunctions. \relates FunctorGridFunction
@@ -102,7 +102,7 @@ namespace AMDiS
     REQUIRES(Concepts::AnyGridFunction<Lhs,Rhs>)>
   auto abs_min(Lhs&& lhs, Rhs&& rhs)
   {
-    return invokeAtQP(Operation::AbsMin{}, std::forward<Lhs>(lhs), std::forward<Rhs>(rhs));
+    return invokeAtQP(Operation::AbsMin{}, FWD(lhs), FWD(rhs));
   }
 
   /// \brief Applies \ref Operation::Clamp to GridFunction. \relates FunctorGridFunction
@@ -110,7 +110,7 @@ namespace AMDiS
     REQUIRES(Concepts::AnyGridFunction<V>)>
   auto clamp(V&& v, T const& lo, T const& hi)
   {
-    return invokeAtQP(Operation::Clamp<T>{lo,hi}, std::forward<V>(v));
+    return invokeAtQP(Operation::Clamp<T>{lo,hi}, FWD(v));
   }
 
   /// \brief Applies \ref Operation::Sqr to GridFunction. \relates FunctorGridFunction
@@ -118,7 +118,7 @@ namespace AMDiS
     REQUIRES(Concepts::AnyGridFunction<T>)>
   auto sqr(T&& value)
   {
-    return invokeAtQP(Operation::Sqr{}, std::forward<T>(value));
+    return invokeAtQP(Operation::Sqr{}, FWD(value));
   }
 
   /// \brief Applies \ref Operation::Pow<p> to GridFunction. \relates FunctorGridFunction
@@ -126,7 +126,7 @@ namespace AMDiS
     REQUIRES(Concepts::AnyGridFunction<T>)>
   auto pow(T&& value)
   {
-    return invokeAtQP(Operation::Pow<p>{}, std::forward<T>(value));
+    return invokeAtQP(Operation::Pow<p>{}, FWD(value));
   }
 
   /// \brief Applies \ref Operation::Pow_ to GridFunction. \relates FunctorGridFunction
@@ -134,7 +134,7 @@ namespace AMDiS
     REQUIRES(Concepts::AnyGridFunction<T>)>
   auto pow(T&& value, int p)
   {
-    return invokeAtQP(Operation::Pow_{p}, std::forward<T>(value));
+    return invokeAtQP(Operation::Pow_{p}, FWD(value));
   }
 
   /// \brief Applies \ref Operation::Get<I> to GridFunction. \relates FunctorGridFunction
@@ -142,7 +142,7 @@ namespace AMDiS
     REQUIRES(Concepts::AnyGridFunction<T>)>
   auto get(T&& value)
   {
-    return invokeAtQP(Operation::Get<I>{}, std::forward<T>(value));
+    return invokeAtQP(Operation::Get<I>{}, FWD(value));
   }
 
   /// \brief Applies \ref Operation::Get_ to GridFunction. \relates FunctorGridFunction
@@ -150,7 +150,7 @@ namespace AMDiS
     REQUIRES(Concepts::AnyGridFunction<T>)>
   auto get(T&& value, std::size_t i)
   {
-    return invokeAtQP(Operation::Get_{i}, std::forward<T>(value));
+    return invokeAtQP(Operation::Get_{i}, FWD(value));
   }
 
   // @}
@@ -163,7 +163,7 @@ namespace AMDiS
     REQUIRES(Concepts::AnyGridFunction<Vec>)>
   auto sum(Vec&& vec)
   {
-    return invokeAtQP([](auto const& v) { return sum(v); }, std::forward<Vec>(vec));
+    return invokeAtQP([](auto const& v) { return sum(v); }, FWD(vec));
   }
 
   /// \brief Applies \ref Operation::UnaryDot to a vector-valued GridFunction. \relates FunctorGridFunction
@@ -171,7 +171,7 @@ namespace AMDiS
     REQUIRES(Concepts::AnyGridFunction<Vec>)>
   auto unary_dot(Vec&& vec)
   {
-    return invokeAtQP(Operation::UnaryDot{}, std::forward<Vec>(vec));
+    return invokeAtQP(Operation::UnaryDot{}, FWD(vec));
   }
 
   /// \brief Applies a \ref one_norm() functor to a vector-valued GridFunction. \relates FunctorGridFunction
@@ -179,7 +179,7 @@ namespace AMDiS
     REQUIRES(Concepts::AnyGridFunction<Vec>)>
   auto one_norm(Vec&& vec)
   {
-    return invokeAtQP([](auto const& v) { return one_norm(v); }, std::forward<Vec>(vec));
+    return invokeAtQP([](auto const& v) { return one_norm(v); }, FWD(vec));
   }
 
   /// \brief Applies \ref Operation::TwoNorm to a vector-valued GridFunction. \relates FunctorGridFunction
@@ -187,7 +187,7 @@ namespace AMDiS
     REQUIRES(Concepts::AnyGridFunction<Vec>)>
   auto two_norm(Vec&& vec)
   {
-    return invokeAtQP(Operation::TwoNorm{}, std::forward<Vec>(vec));
+    return invokeAtQP(Operation::TwoNorm{}, FWD(vec));
   }
 
   /// \brief Applies a \ref p_norm() functor to a vector-valued GridFunction. \relates FunctorGridFunction
@@ -195,7 +195,7 @@ namespace AMDiS
     REQUIRES(Concepts::AnyGridFunction<Vec>)>
   auto p_norm(Vec&& vec)
   {
-    return invokeAtQP([](auto const& v) { return p_norm<p>(v); }, std::forward<Vec>(vec));
+    return invokeAtQP([](auto const& v) { return p_norm<p>(v); }, FWD(vec));
   }
 
   /// \brief Applies a \ref infty_norm() functor to a vector-valued GridFunction. \relates FunctorGridFunction
@@ -203,7 +203,7 @@ namespace AMDiS
     REQUIRES(Concepts::AnyGridFunction<Vec>)>
   auto infty_norm(Vec&& vec)
   {
-    return invokeAtQP([](auto const& v) { return infty_norm(v); }, std::forward<Vec>(vec));
+    return invokeAtQP([](auto const& v) { return infty_norm(v); }, FWD(vec));
   }
 
   /// \brief Applies \ref Operation::Trans to a matrix-valued GridFunction.\relates FunctorGridFunction
@@ -211,7 +211,7 @@ namespace AMDiS
     REQUIRES(Concepts::AnyGridFunction<Mat>)>
   auto trans(Mat&& mat)
   {
-    return invokeAtQP(Operation::Trans{}, std::forward<Mat>(mat));
+    return invokeAtQP(Operation::Trans{}, FWD(mat));
   }
 
   // @}
@@ -226,7 +226,7 @@ namespace AMDiS
   auto dot(Lhs&& lhs, Rhs&& rhs)
   {
     return invokeAtQP(Operation::Dot{},
-      std::forward<Lhs>(lhs), std::forward<Rhs>(rhs));
+      FWD(lhs), FWD(rhs));
   }
 
   /// \brief Applies a distance-functor to two vector-valued GridFunctions.\relates FunctorGridFunction
@@ -236,7 +236,7 @@ namespace AMDiS
   {
     using namespace Operation;
     return invokeAtQP(compose(TwoNorm{}, Minus{}),
-      std::forward<Lhs>(lhs), std::forward<Rhs>(rhs));
+      FWD(lhs), FWD(rhs));
   }
 
   /// \brief Applies an \ref outer() functor to two vector-valued GridFunctions. \relates FunctorGridFunction
@@ -245,7 +245,7 @@ namespace AMDiS
   auto outer(Lhs&& lhs, Rhs&& rhs)
   {
     return invokeAtQP([](auto const& v, auto const& w) { return outer(v,w); },
-      std::forward<Lhs>(lhs), std::forward<Rhs>(rhs));
+      FWD(lhs), FWD(rhs));
   }
 
   // @}
diff --git a/src/amdis/operations/Basic.hpp b/src/amdis/operations/Basic.hpp
index ed95863a2a5dda2c85ca16824ae7b407cd1b0dae..304023d1af9fef68e46f171088aa51b813204b0e 100644
--- a/src/amdis/operations/Basic.hpp
+++ b/src/amdis/operations/Basic.hpp
@@ -117,7 +117,7 @@ namespace AMDiS
       template <class... Ts>
       constexpr auto&& operator()(Ts&&... args) const
       {
-        return std::get<I>(std::forward_as_tuple(std::forward<Ts>(args)...));
+        return std::get<I>(std::forward_as_tuple(FWD(args)...));
       }
     };
 
diff --git a/src/amdis/operations/Composer.hpp b/src/amdis/operations/Composer.hpp
index 2e1338f0fa02ede1bdd03adf34b5f9679f6bca2b..586cc45b0fbae9a8bdc88aea904aeff6b1a5d574 100644
--- a/src/amdis/operations/Composer.hpp
+++ b/src/amdis/operations/Composer.hpp
@@ -32,8 +32,8 @@ namespace AMDiS
       template <class F_, class... Gs_,
         REQUIRES( Concepts::Similar<Types<F,Gs...>, Types<F_,Gs_...>>) >
       constexpr Composer(F_&& f, Gs_&&... gs)
-        : f_(std::forward<F_>(f))
-        , gs_(std::forward<Gs_>(gs)...)
+        : f_(FWD(f))
+        , gs_(FWD(gs)...)
       {}
 
       template <class... Ts>
@@ -56,7 +56,7 @@ namespace AMDiS
       template <class F_, class... Gs_>
       static constexpr type build(F_&& f, Gs_&&... gs)
       {
-        return type{std::forward<F_>(f), std::forward<Gs_>(gs)...};
+        return type{FWD(f), FWD(gs)...};
       }
     };
 #endif
@@ -65,8 +65,7 @@ namespace AMDiS
     template <class F, class... Gs>
     constexpr auto compose(F&& f, Gs&&... gs)
     {
-      return ComposerBuilder<std::decay_t<F>, std::decay_t<Gs>...>::build(
-        std::forward<F>(f), std::forward<Gs>(gs)...);
+      return ComposerBuilder<TYPEOF(f), TYPEOF(gs)...>::build(FWD(f), FWD(gs)...);
     }
 
     // Polynomial order or composed function combines the orders of the sub-functions
@@ -97,7 +96,7 @@ namespace AMDiS
       template <class F_>
       static constexpr F build(F_&& f)
       {
-        return F{std::forward<F_>(f)};
+        return F{FWD(f)};
       }
     };
 #endif
diff --git a/src/amdis/typetree/RangeType.hpp b/src/amdis/typetree/RangeType.hpp
index 0e36925ec9476e92d8b28445c44705e4c466698a..38b2ecec78344a40a6df2c2b21638da5a262aa4b 100644
--- a/src/amdis/typetree/RangeType.hpp
+++ b/src/amdis/typetree/RangeType.hpp
@@ -43,7 +43,7 @@ namespace AMDiS
     {
       using LocalBasis = typename Node::FiniteElement::Traits::LocalBasisType;
       using T = typename LocalBasis::Traits::RangeType;
-      using type = std::decay_t<decltype(std::declval<R>() * std::declval<T>())>;
+      using type = remove_cvref_t<decltype(std::declval<R>() * std::declval<T>())>;
     };
 
     // Power node
diff --git a/src/amdis/typetree/Traversal.hpp b/src/amdis/typetree/Traversal.hpp
index 3a02e7422776912b5cc025741a5375111ecad5af..a0255eb3112c2f1c6176f68f09c40db090be7320 100644
--- a/src/amdis/typetree/Traversal.hpp
+++ b/src/amdis/typetree/Traversal.hpp
@@ -5,6 +5,7 @@
 #include <dune/typetree/visitor.hh>
 
 #include <amdis/common/Loops.hpp>
+#include <amdis/common/TypeTraits.hpp>
 
 namespace AMDiS
 {
@@ -78,28 +79,28 @@ namespace AMDiS
       using Node = std::remove_reference_t<N>;
       using Visitor = std::remove_reference_t<V>;
 
-      v.pre(std::forward<N>(n),tp);
+      v.pre(FWD(n),tp);
 
       auto const deg = hybridDegree(NodeTag{}, n);
       forEach(Dune::range(deg), [&](auto const _k)
       {
         // always call beforeChild(), regardless of the value of visit
-        v.beforeChild(std::forward<N>(n),n.child(_k),tp,_k);
+        v.beforeChild(FWD(n),n.child(_k),tp,_k);
 
         // descend to child
         using C = typename HybridChildType<Node, decltype(_k)>::type;
         const bool visit = Visitor::template VisitChild<Node,C,TreePath>::value;
-        TraverseTree<Dune::TypeTree::NodeTag<C>,visit>::apply(n.child(_k),std::forward<V>(v),push_back(tp, _k));
+        TraverseTree<Dune::TypeTree::NodeTag<C>,visit>::apply(n.child(_k),FWD(v),push_back(tp, _k));
 
         // always call afterChild(), regardless of the value of visit
-        v.afterChild(std::forward<N>(n),n.child(_k),tp,_k);
+        v.afterChild(FWD(n),n.child(_k),tp,_k);
 
         // if this is not the last child, call infix callback
         if (notLastChild(_k, deg))
-          v.in(std::forward<N>(n),tp);
+          v.in(FWD(n),tp);
       });
 
-      v.post(std::forward<N>(n),tp);
+      v.post(FWD(n),tp);
     }
   };
 
@@ -110,7 +111,7 @@ namespace AMDiS
     template <typename N, typename V, typename TreePath>
     static void apply(N&& n, V&& v, TreePath const& tp)
     {
-      v.leaf(std::forward<N>(n),tp);
+      v.leaf(FWD(n),tp);
     }
   };
 
@@ -131,7 +132,7 @@ namespace AMDiS
     using Node = std::remove_reference_t<Tree>;
     using NodeTag = Dune::TypeTree::NodeTag<Node>;
     using TreePath = Dune::TypeTree::HybridTreePath<>;
-    TraverseTree<NodeTag>::apply(std::forward<Tree>(tree), std::forward<Visitor>(visitor), TreePath{});
+    TraverseTree<NodeTag>::apply(FWD(tree), FWD(visitor), TreePath{});
   }
 
 } // end namespace AMDiS
diff --git a/src/amdis/typetree/TreeContainer.hpp b/src/amdis/typetree/TreeContainer.hpp
index cd013a67158ab5ef5033b0d4921fb5c4898151bf..4bad3c795fb8df1a029cddb988caf2a4d9c51319 100644
--- a/src/amdis/typetree/TreeContainer.hpp
+++ b/src/amdis/typetree/TreeContainer.hpp
@@ -11,6 +11,7 @@
 #include <dune/typetree/treepath.hh>
 
 #include <amdis/common/Apply.hpp>
+#include <amdis/common/TypeTraits.hpp>
 
 // NOTE: backport of dune/typetree/treecontainer.hh
 
@@ -135,7 +136,7 @@ namespace AMDiS
     template<class Container>
     auto makeTreeContainerVectorBackend(Container&& container)
     {
-      return TreeContainerVectorBackend<std::decay_t<Container>>(std::forward<Container>(container));
+      return TreeContainerVectorBackend<remove_cvref_t<Container>>(FWD(container));
     }
 
   } // end namespace Impl
@@ -192,7 +193,7 @@ namespace AMDiS
      * \brief Alias to container type generated by makeTreeContainer for given value and tree type
      */
     template<class Value, class Tree>
-    using TreeContainer = std::decay_t<decltype(makeTreeContainer<Value>(std::declval<const Tree&>()))>;
+    using TreeContainer = TYPEOF(makeTreeContainer<Value>(std::declval<const Tree&>()));
 
     //! \} group TypeTree