diff --git a/src/mesh/ItemValueUtils.hpp b/src/mesh/ItemValueUtils.hpp
index 6e73e0abeb215107c0bbe542b54d5916479dbc3e..a1039fdbdc8933c27d6ce19ec978894b329520c1 100644
--- a/src/mesh/ItemValueUtils.hpp
+++ b/src/mesh/ItemValueUtils.hpp
@@ -14,42 +14,18 @@ template <typename DataType, ItemType item_type, typename ConnectivityPtr>
 std::remove_const_t<DataType>
 min(const ItemValue<DataType, item_type, ConnectivityPtr>& item_value)
 {
-  using ItemValueType = ItemValue<DataType, item_type, ConnectivityPtr>;
-  using data_type     = std::remove_const_t<typename ItemValueType::data_type>;
-  using index_type    = typename ItemValueType::index_type;
-
-  const auto& is_owned = [&](const IConnectivity& connectivity) {
-    Assert((connectivity.dimension() > 0) and (connectivity.dimension() <= 3), "unexpected connectivity dimension");
-
-    switch (connectivity.dimension()) {
-    case 1: {
-      const auto& connectivity_1d = static_cast<const Connectivity1D&>(connectivity);
-      return connectivity_1d.isOwned<item_type>();
-      break;
-    }
-    case 2: {
-      const auto& connectivity_2d = static_cast<const Connectivity2D&>(connectivity);
-      return connectivity_2d.isOwned<item_type>();
-      break;
-    }
-    case 3: {
-      const auto& connectivity_3d = static_cast<const Connectivity3D&>(connectivity);
-      return connectivity_3d.isOwned<item_type>();
-      break;
-    }
-    default: {
-      throw UnexpectedError("unexpected dimension");
-    }
-    }
-  }(*item_value.connectivity_ptr());
+  using ItemValueType   = ItemValue<DataType, item_type, ConnectivityPtr>;
+  using ItemIsOwnedType = ItemValue<const bool, item_type>;
+  using data_type       = std::remove_const_t<typename ItemValueType::data_type>;
+  using index_type      = typename ItemValueType::index_type;
 
-  using IsOwnedType = std::remove_reference_t<decltype(is_owned)>;
+  static_assert(not std::is_same_v<data_type, bool>, "min cannot be called on boolean arrays");
 
   class ItemValueMin
   {
    private:
     const ItemValueType& m_item_value;
-    const IsOwnedType& m_is_owned;
+    const ItemIsOwnedType m_is_owned;
 
    public:
     PUGS_INLINE
@@ -86,8 +62,32 @@ min(const ItemValue<DataType, item_type, ConnectivityPtr>& item_value)
     }
 
     PUGS_INLINE
-    ItemValueMin(const ItemValueType& item_value, const IsOwnedType& is_owned)
-      : m_item_value(item_value), m_is_owned(is_owned)
+    ItemValueMin(const ItemValueType& item_value)
+      : m_item_value(item_value), m_is_owned([&](const IConnectivity& connectivity) {
+          Assert((connectivity.dimension() > 0) and (connectivity.dimension() <= 3),
+                 "unexpected connectivity dimension");
+
+          switch (connectivity.dimension()) {
+          case 1: {
+            const auto& connectivity_1d = static_cast<const Connectivity1D&>(connectivity);
+            return connectivity_1d.isOwned<item_type>();
+            break;
+          }
+          case 2: {
+            const auto& connectivity_2d = static_cast<const Connectivity2D&>(connectivity);
+            return connectivity_2d.isOwned<item_type>();
+            break;
+          }
+          case 3: {
+            const auto& connectivity_3d = static_cast<const Connectivity3D&>(connectivity);
+            return connectivity_3d.isOwned<item_type>();
+            break;
+          }
+          default: {
+            throw UnexpectedError("unexpected dimension");
+          }
+          }
+        }(*item_value.connectivity_ptr()))
     {
       ;
     }
@@ -96,7 +96,7 @@ min(const ItemValue<DataType, item_type, ConnectivityPtr>& item_value)
     ~ItemValueMin() = default;
   };
 
-  const DataType local_min = ItemValueMin{item_value, is_owned};
+  const DataType local_min = ItemValueMin{item_value};
   return parallel::allReduceMin(local_min);
 }
 
@@ -104,42 +104,17 @@ template <typename DataType, ItemType item_type, typename ConnectivityPtr>
 std::remove_const_t<DataType>
 max(const ItemValue<DataType, item_type, ConnectivityPtr>& item_value)
 {
-  using ItemValueType = ItemValue<DataType, item_type, ConnectivityPtr>;
-  using data_type     = std::remove_const_t<typename ItemValueType::data_type>;
-  using index_type    = typename ItemValueType::index_type;
-
-  const auto& is_owned = [&](const IConnectivity& connectivity) {
-    Assert((connectivity.dimension() > 0) and (connectivity.dimension() <= 3), "unexpected connectivity dimension");
-
-    switch (connectivity.dimension()) {
-    case 1: {
-      const auto& connectivity_1d = static_cast<const Connectivity1D&>(connectivity);
-      return connectivity_1d.isOwned<item_type>();
-      break;
-    }
-    case 2: {
-      const auto& connectivity_2d = static_cast<const Connectivity2D&>(connectivity);
-      return connectivity_2d.isOwned<item_type>();
-      break;
-    }
-    case 3: {
-      const auto& connectivity_3d = static_cast<const Connectivity3D&>(connectivity);
-      return connectivity_3d.isOwned<item_type>();
-      break;
-    }
-    default: {
-      throw UnexpectedError("unexpected dimension");
-    }
-    }
-  }(*item_value.connectivity_ptr());
-
-  using IsOwnedType = std::remove_reference_t<decltype(is_owned)>;
+  using ItemValueType   = ItemValue<DataType, item_type, ConnectivityPtr>;
+  using ItemIsOwnedType = ItemValue<const bool, item_type>;
+  using data_type       = std::remove_const_t<typename ItemValueType::data_type>;
+  using index_type      = typename ItemValueType::index_type;
 
+  static_assert(not std::is_same_v<data_type, bool>, "min cannot be called on boolean arrays");
   class ItemValueMax
   {
    private:
     const ItemValueType& m_item_value;
-    const IsOwnedType& m_is_owned;
+    const ItemIsOwnedType m_is_owned;
 
    public:
     PUGS_INLINE
@@ -176,8 +151,32 @@ max(const ItemValue<DataType, item_type, ConnectivityPtr>& item_value)
     }
 
     PUGS_INLINE
-    ItemValueMax(const ItemValueType& item_value, const IsOwnedType& is_owned)
-      : m_item_value(item_value), m_is_owned(is_owned)
+    ItemValueMax(const ItemValueType& item_value)
+      : m_item_value(item_value), m_is_owned([&](const IConnectivity& connectivity) {
+          Assert((connectivity.dimension() > 0) and (connectivity.dimension() <= 3),
+                 "unexpected connectivity dimension");
+
+          switch (connectivity.dimension()) {
+          case 1: {
+            const auto& connectivity_1d = static_cast<const Connectivity1D&>(connectivity);
+            return connectivity_1d.isOwned<item_type>();
+            break;
+          }
+          case 2: {
+            const auto& connectivity_2d = static_cast<const Connectivity2D&>(connectivity);
+            return connectivity_2d.isOwned<item_type>();
+            break;
+          }
+          case 3: {
+            const auto& connectivity_3d = static_cast<const Connectivity3D&>(connectivity);
+            return connectivity_3d.isOwned<item_type>();
+            break;
+          }
+          default: {
+            throw UnexpectedError("unexpected dimension");
+          }
+          }
+        }(*item_value.connectivity_ptr()))
     {
       ;
     }
@@ -194,42 +193,18 @@ template <typename DataType, ItemType item_type>
 std::remove_const_t<DataType>
 sum(const ItemValue<DataType, item_type>& item_value)
 {
-  using ItemValueType = ItemValue<DataType, item_type>;
-  using data_type     = std::remove_const_t<typename ItemValueType::data_type>;
-  using index_type    = typename ItemValueType::index_type;
-
-  const auto& is_owned = [&](const IConnectivity& connectivity) {
-    Assert((connectivity.dimension() > 0) and (connectivity.dimension() <= 3), "unexpected connectivity dimension");
-
-    switch (connectivity.dimension()) {
-    case 1: {
-      const auto& connectivity_1d = static_cast<const Connectivity1D&>(connectivity);
-      return connectivity_1d.isOwned<item_type>();
-      break;
-    }
-    case 2: {
-      const auto& connectivity_2d = static_cast<const Connectivity2D&>(connectivity);
-      return connectivity_2d.isOwned<item_type>();
-      break;
-    }
-    case 3: {
-      const auto& connectivity_3d = static_cast<const Connectivity3D&>(connectivity);
-      return connectivity_3d.isOwned<item_type>();
-      break;
-    }
-    default: {
-      throw UnexpectedError("unexpected dimension");
-    }
-    }
-  }(*item_value.connectivity_ptr());
+  using ItemValueType   = ItemValue<DataType, item_type>;
+  using ItemIsOwnedType = ItemValue<const bool, item_type>;
+  using data_type       = std::remove_const_t<typename ItemValueType::data_type>;
+  using index_type      = typename ItemValueType::index_type;
 
-  using IsOwnedType = std::remove_reference_t<decltype(is_owned)>;
+  static_assert(not std::is_same_v<data_type, bool>, "sum cannot be called on boolean arrays");
 
   class ItemValueSum
   {
    private:
     const ItemValueType& m_item_value;
-    const IsOwnedType& m_is_owned;
+    const ItemIsOwnedType m_is_owned;
 
    public:
     PUGS_INLINE
@@ -268,7 +243,32 @@ sum(const ItemValue<DataType, item_type>& item_value)
     }
 
     PUGS_INLINE
-    ItemValueSum(const ItemValueType& item_value) : m_item_value(item_value), m_is_owned{is_owned(item_value)}
+    ItemValueSum(const ItemValueType& item_value)
+      : m_item_value(item_value), m_is_owned([&](const IConnectivity& connectivity) {
+          Assert((connectivity.dimension() > 0) and (connectivity.dimension() <= 3),
+                 "unexpected connectivity dimension");
+
+          switch (connectivity.dimension()) {
+          case 1: {
+            const auto& connectivity_1d = static_cast<const Connectivity1D&>(connectivity);
+            return connectivity_1d.isOwned<item_type>();
+            break;
+          }
+          case 2: {
+            const auto& connectivity_2d = static_cast<const Connectivity2D&>(connectivity);
+            return connectivity_2d.isOwned<item_type>();
+            break;
+          }
+          case 3: {
+            const auto& connectivity_3d = static_cast<const Connectivity3D&>(connectivity);
+            return connectivity_3d.isOwned<item_type>();
+            break;
+          }
+          default: {
+            throw UnexpectedError("unexpected dimension");
+          }
+          }
+        }(*item_value.connectivity_ptr()))
     {
       ;
     }
@@ -277,7 +277,7 @@ sum(const ItemValue<DataType, item_type>& item_value)
     ~ItemValueSum() = default;
   };
 
-  const DataType local_sum = ItemValueSum{item_value, is_owned};
+  const DataType local_sum = ItemValueSum{item_value};
   return parallel::allReduceSum(local_sum);
 }