diff --git a/src/mesh/ItemArray.hpp b/src/mesh/ItemArray.hpp
index 78e5f8dd64c430ec8149c3e608d444897987f108..1a2b004c9533921ab6531b6fa73c9a955badff57 100644
--- a/src/mesh/ItemArray.hpp
+++ b/src/mesh/ItemArray.hpp
@@ -47,6 +47,19 @@ class ItemArray
     return image;
   }
 
+  template <typename ConnectivityPtr2>
+  friend PUGS_INLINE void copy_to(const ItemArray<std::add_const_t<DataType>, item_type, ConnectivityPtr>& source,
+                                  const ItemArray<DataType, item_type, ConnectivityPtr2>& destination);
+
+  template <typename ConnectivityPtr2>
+  friend PUGS_INLINE void
+  copy_to(const ItemArray<DataType, item_type, ConnectivityPtr>& source,
+          const ItemArray<std::remove_const_t<DataType>, item_type, ConnectivityPtr2>& destination)
+  {
+    Assert(destination.connectivity_ptr() == source.connectivity_ptr());
+    copy_to(source.m_values, destination.m_values);
+  }
+
   PUGS_INLINE
   bool
   isBuilt() const noexcept
diff --git a/src/mesh/ItemValue.hpp b/src/mesh/ItemValue.hpp
index 0f7fe61717fc9d8c571d0107b5ae422cc6b911bb..ebc5f40511a0be6d1eeb519a0660b494d268f150 100644
--- a/src/mesh/ItemValue.hpp
+++ b/src/mesh/ItemValue.hpp
@@ -47,6 +47,19 @@ class ItemValue
     return image;
   }
 
+  template <typename ConnectivityPtr2>
+  friend PUGS_INLINE void copy_to(const ItemValue<std::add_const_t<DataType>, item_type, ConnectivityPtr>& source,
+                                  const ItemValue<DataType, item_type, ConnectivityPtr2>& destination);
+
+  template <typename ConnectivityPtr2>
+  friend PUGS_INLINE void
+  copy_to(const ItemValue<DataType, item_type, ConnectivityPtr>& source,
+          const ItemValue<std::remove_const_t<DataType>, item_type, ConnectivityPtr2>& destination)
+  {
+    Assert(destination.connectivity_ptr() == source.connectivity_ptr());
+    copy_to(source.m_values, destination.m_values);
+  }
+
   PUGS_INLINE
   bool
   isBuilt() const noexcept
diff --git a/tests/test_ItemArray.cpp b/tests/test_ItemArray.cpp
index 05cdb548aaa532b2642faf870242961126e398d0..2a76275324c4922ed0bad182ebcfa106c3d9b462 100644
--- a/tests/test_ItemArray.cpp
+++ b/tests/test_ItemArray.cpp
@@ -169,11 +169,15 @@ TEST_CASE("ItemArray", "[mesh]")
     CellArray<const int> const_cell_array;
     const_cell_array = copy(cell_array);
 
+    CellArray<int> duplicated_cell_array{connectivity, cell_array.sizeOfArrays()};
+    copy_to(const_cell_array, duplicated_cell_array);
+
     cell_array.fill(0);
 
     REQUIRE(is_same(cell_array, 0));
     REQUIRE(is_same(cell_array_const_view, 0));
     REQUIRE(is_same(const_cell_array, static_cast<std::int64_t>(parallel::rank())));
+    REQUIRE(is_same(duplicated_cell_array, static_cast<std::int64_t>(parallel::rank())));
   }
 
   SECTION("WeakItemArray")
diff --git a/tests/test_ItemValue.cpp b/tests/test_ItemValue.cpp
index a4bc710471bb35b92871e6751c72176c43c6fefd..1c4ab49faf757cc0b2e871f9bf4e0ba33061ece7 100644
--- a/tests/test_ItemValue.cpp
+++ b/tests/test_ItemValue.cpp
@@ -191,6 +191,19 @@ TEST_CASE("ItemValue", "[mesh]")
       Array<size_t> values{3 + cell_value.numberOfItems()};
       REQUIRE_THROWS_AS(cell_value = values, AssertError);
     }
+
+    SECTION("invalid copy_to")
+    {
+      const Mesh<Connectivity<2>>& mesh_2d   = *MeshDataBaseForTests::get().cartesianMesh2D();
+      const Connectivity<2>& connectivity_2d = mesh_2d.connectivity();
+
+      const Mesh<Connectivity<3>>& mesh_3d   = *MeshDataBaseForTests::get().cartesianMesh3D();
+      const Connectivity<3>& connectivity_3d = mesh_3d.connectivity();
+
+      CellValue<int> cell_2d_value{connectivity_2d};
+      CellValue<int> cell_3d_value{connectivity_3d};
+      REQUIRE_THROWS_AS(copy_to(cell_2d_value, cell_3d_value), AssertError);
+    }
   }
 #endif   // NDEBUG
 }