Repository: eclipse-iceoryx/iceoryx (C++)

Issue:
Move `MoveAndCopyHelper` to `iceoryx_hoofs/design`
## Brief feature description

Currently, some classes in our codebase use assignment in the constructor (ctor) to avoid code duplication, as seen in issue #1517 . However, it's noted in issue #1686  that self-assignment cannot happen in the ctor. Therefore, an alternative approach should be adopted to replace the current implementation.

One method involves placing the shared logical code within a separate function, hereafter referred to as `copy_and_move_impl`. This function is then called within the ctor and assignment operations, using template parameters to specify the method of member initialization.

`MoveAndCopyHelper` has been implemented in PR #2105 and applied to `FixedPositionContainer`. This helper controls through template parameter types, specifically an enum class `MoveAndCopyOperations`.

### Example usage

When the helper is invoked with the template (referred to as `Opt`) set to `MoveAndCopyOperations::CopyConstructor`, it would look something like:

```c
#include "iox/detail/fixed_position_container_helper.hpp"

// for class A ...

inline A::A(const A& rhs) noexcept
{
    copy_and_move_impl<detail::MoveAndCopyOperations::CopyConstructor>(rhs);
}

inline A::A(A&& rhs) noexcept
{
    copy_and_move_impl<detail::MoveAndCopyOperations::MoveConstructor>(std::forward<A>(rhs));
}

... 

template <detail::MoveAndCopyOperations Opt, typename RhsType, /* other template */>
inline void A::copy_and_move_impl(RhsType&& rhs) noexcept
{
    // alias helper struct
    using Helper = detail::MoveAndCopyHelper<Opt>;
    
    // determine by `Opt`
    constexpr bool_is_ctor = Helper::is_ctor();
    constexpr bool is_move = Helper::is_move(); 
    
    // if you want to transfer rhs.m_data array to this.m_data
    for (uint64_t i = 0; i < rhs.size(); ++i)
    {
	 if constexpr (is_move)
        {
            Helper::transfer(m_data[i], std::move(rhs.m_data[i]));
        }
        else
        {
            Helper::transfer(m_data[i], rhs.m_data[i]);
        }
    }
    
    // if you want to initialize a status array in ctor operation
    if constexpr (is_ctor)
    {
        initialize_status();
    }
}
```

## Detailed information

### Cons
Integrating this helper into the `design` can be beneficial when the differences between the constructor and assignment are minimal. It allows for the creation of a unified template function within the class to manage these operations, with the behavior inside controlled by the `Opt` parameter. Simultaneously, it helps to avoid situations where the ctor invokes assignment, especially in cases where the assignment is deleted.

## Evaluate `copy_or_move`

If `move_or_copy` can be implemented correctly, the code mentioned above can be simplified as

```c
...
// if you want to transfer rhs.m_data array to this.m_data
    for (uint64_t i = 0; i < rhs.size(); ++i)
    {
            Helper::transfer(m_data[i], Helper::move_or_copy(rhs.m_data[i]));
    }
...
```
 
However, the following `move_or_copy` will call move ctor at return syntax.  
```c
template <typename T>
 static inline constexpr auto move_or_copy(T&& value) noexcept
 {
     if constexpr (is_move())
     {
         return std::move(std::forward<T>(value));
     }
     else
     {
         return std::cref(std::forward<T>(value));
     }
}
```
You can see the details at [here](https://godbolt.org/z/heTcqoeo7).

Short summary:
- So far, I have no idea how to implement it correctly.

Implement `move_or_copy` for `MoveAndCopyHelper`
## Brief feature description

The function `move_or_copy` is mentioned in #2113. Implement this function can enhance the `MoveAndCopyHelper`.
A draft of `move_or_copy` is implemented [here](https://godbolt.org/z/KP83Yhn4h).

## Detailed information

With `move_or_copy`, the following code

```cpp
// transfer data example
template <MoveAndCopyOperations Opt, typename RhsType>
void Test::copy_and_move_impl(RhsType&& rhs)
{
  // you can set alias to simplify code
  using Helper = MoveAndCopyHelper<Opt>;

  // you can determine the current `Opt` at compile time for compile-time branching decisions.
  constexpr bool is_ctor = Helper::is_ctor();
  constexpr bool is_move = Helper::is_move();
  
  for (uint64_t i = 0; i < rhs.size(); ++i)
  {
      if constexpr (is_move)
      {
          Helper::transfer(m_data[i], std::move(rhs.data[i]));
      }
      else
      {
          Helper::transfer(m_data[i], rhs.data[i]);
      }
  }
}
```

can be simplified as

```cpp
template <MoveAndCopyOperations Opt, typename RhsType>
void Test::copy_and_move_impl(RhsType&& rhs)
{
  // you can set alias to simplify code
  using Helper = MoveAndCopyHelper<Opt>;

  // you can determine the current `Opt` at compile time for compile-time branching decisions.
  constexpr bool is_ctor = Helper::is_ctor();
  constexpr bool is_move = Helper::is_move();
  
  for (uint64_t i = 0; i < rhs.size(); ++i)
  {
       Helper::transfer(m_data[i], Helper::move_or_copy(rhs.data[i]));
  }
}
```




Fix (patch):
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 0cfb84e658..72fd0477fa 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -197,6 +197,10 @@ necessary, do the following:
 1. Contact the maintainers beforehand by opening an issue to discuss the necessity
 1. If accepted, add the new header to `tools/scripts/used-headers.txt` for the CI to pass
 
+### Eliminating code duplication
+
+1. In some cases, the code in the constructor and assignment operations may be largely duplicated. It is encouraged to move this duplicated code into a separate function (e.g., `copy_and_move_impl`) for better reuse. Additionally, the `MoveAndCopyHelper` in `iceoryx/design` (refer to [MoveAndCopyHelper](./doc/design/move_and_copy_helper.md)) offers some functionalities that make this process easier.
+
 ## Folder structure
 
 The folder structure boils down to:
diff --git a/doc/design/move_and_copy_helper.md b/doc/design/move_and_copy_helper.md
new file mode 100644
index 0000000000..c2dbaae2a0
--- /dev/null
+++ b/doc/design/move_and_copy_helper.md
@@ -0,0 +1,152 @@
+# Move And Copy Helper
+
+## Summary and problem description
+
+Currently, some classes in our codebase use assignment operator in the constructor (ctor) to avoid code duplication, as seen in issue [#1517](https://github.com/eclipse-iceoryx/iceoryx/issues/1517) . However, it's noted in issue [#1686](https://github.com/eclipse-iceoryx/iceoryx/issues/1686) that self-assignment should not happen in the ctor. Therefore, an alternative approach needs to be adopted to replace the current implementation.
+
+One method involves placing the shared logical code within a separate function, hereafter referred to as `copy_and_move_impl`. This function is then called within the ctor and assignment operations, using template parameters to specify the method of member initialization.
+
+## Premise
+
+When a class performs highly consistent tasks during construction (ctor) and assignment, implementers often extract the repetitive parts into a separate `copy_and_move_impl`. However, there are inevitably minor differences between move, copy, and ctor, assignment (for example, during ctor, specific variables need to be initialized to avoid garbage values affecting subsequent behaviors, etc...). In these cases, the `MoveAndCopyHelper` can be used to simplify the code.
+
+## Terminology
+
+- `MoveAndCopyOperations`: an enum class, including
+
+    - `CopyConstructor`
+    - `MoveConstructor`
+    - `CopyAssignment`
+    - `MoveAssignment`
+
+## Goals
+
+The purpose of the `MoveAndCopyHelper` is:
+- To allow special constructors to indicate the source of the call (e.g., CopyConstructor) when calling `copy_and_move_impl`.
+- To provide a consistent way of expressing data exchange in `copy_and_move_impl`.
+- To offer a way to ignore `MoveAndCopyOperations` and forcibly use ctor or assignment, facilitating users' needs in special circumstances.
+
+## Design
+
+- Provide the enum class `MoveAndCopyOperations` to describe the expected behavior of member variables during initialization (e.g., using copy or move). Passing this enum as a template parameter to `copy_and_move_impl` ensures whether special constructors are called as expected.
+- Provide functions like `transfer` to ensure that the exchange process of member variables conforms to `MoveAndCopyOperations`.
+
+### Scenario
+
+#### Transfer
+Presently, there are three functions: `transfer`, `create_new`, and `assign`. The scenarios outlined below briefly describe the appropriate usage for each function.
+
+- `transfer`: This is a general-purpose function for data transfer. It is recommended for use in cases where you are not dealing with potentially uninitialized memory.
+- `create_new`: In certain instances, particularly during constructor operations, some class members are lazy initialization. For these members, the copy or move constructor must be employed, even when they are being accessed via the assignment operator.
+- `assign`: TBD.
+
+### Code example
+
+```cpp
+// header
+
+#include "iox/move_and_copy_helper.hpp"
+
+constexpr uint64_t CAPACITY {1024};
+
+class Test
+{
+  public:
+    Test();
+    Test(const Test&);
+    Test(Test&&);
+    Test& operator=(const Test&);
+    Test& operator=(Test&&);
+
+    uint64_t size();
+
+  private:
+    int m_data[CAPACITY];
+    uint64_t m_size{0};
+}
+
+// implementation
+Test::Test(const Test& rhs)
+{
+    copy_and_move_impl<MoveAndCopyOperations::CopyConstructor>(rhs);
+}
+
+Test::Test(Test&& rhs)
+{
+     copy_and_move_impl<MoveAndCopyOperations::MoveConstructor>(rhs);
+}
+
+Test& Test::operator=(const Test& rhs)
+{
+    // you may do self-assignment check in copy_and_move_impl
+    if (this != &rhs)
+    {
+        copy_and_move_impl<MoveAndCopyOperations::CopyAssignment>(rhs);
+    }
+
+    return *this;
+}
+
+Test& Test::operator=(Test&& rhs)
+{
+    // you may do self-assignment check in copy_and_move_impl
+    if (this != &rhs)
+    {
+        copy_and_move_impl<MoveAndCopyOperations::MoveAssignment>(std::move(rhs));
+    }
+    return *this;
+}
+
+void Test::size()
+{
+    return m_size;
+}
+
+template <MoveAndCopyOperations Opt, typename RhsType>
+void Test::copy_and_move_impl(RhsType&& rhs)
+{
+    // you can set alias to simplify code
+    using Helper = MoveAndCopyHelper<Opt>;
+
+    // you can determine the current 'Opt' at compile time for compile-time branching decisions.
+    constexpr bool is_ctor = Helper::is_ctor;
+    constexpr bool is_move = Helper::is_move;
+
+    // // self assignment check if needed
+    // if constexpr (!is_ctor)
+    // {
+    //     if (this == &rhs)
+    //     {
+    //         return;
+    //     }
+    // }
+
+    // for ctor operation
+    if constexpr (is_ctor)
+    {
+        // reset something if needed
+        reset_something();
+    }
+
+    // transfer data example
+    for (uint64_t i = 0; i < rhs.size(); ++i)
+    {
+        // @Recommended method
+        Helper::transfer(m_data[i], Helper::move_or_copy(rhs.data[i]));
+
+        // @Alternative method
+        // if constexpr (is_move)
+        // {
+        //     Helper::transfer(m_data[i], std::move(rhs.data[i]));
+        // }
+        // else
+        // {
+        //     Helper::transfer(m_data[i], rhs.data[i]);
+        // }
+    }
+}
+```
+
+For more examples, see
+
+- `iceoryx_dust/container/detail/fixed_position_container.inl`
diff --git a/iceoryx_dust/container/include/iox/detail/fixed_position_container.inl b/iceoryx_dust/container/include/iox/detail/fixed_position_container.inl
index 8be6a9b4e5..a7a2f50c61 100644
--- a/iceoryx_dust/container/include/iox/detail/fixed_position_container.inl
+++ b/iceoryx_dust/container/include/iox/detail/fixed_position_container.inl
@@ -18,7 +18,6 @@
 #ifndef IOX_DUST_CONTAINER_DETAIL_FIXED_POSITION_CONTAINER_INL
 #define IOX_DUST_CONTAINER_DETAIL_FIXED_POSITION_CONTAINER_INL
 
-#include "iox/detail/fixed_position_container_helper.hpp"
 #include "iox/fixed_position_container.hpp"
 
 namespace iox
@@ -56,13 +55,13 @@ inline FixedPositionContainer<T, CAPACITY>::~FixedPositionContainer() noexcept
 template <typename T, uint64_t CAPACITY>
 inline FixedPositionContainer<T, CAPACITY>::FixedPositionContainer(const FixedPositionContainer& rhs) noexcept
 {
-    copy_and_move_impl<detail::MoveAndCopyOperations::CopyConstructor>(rhs);
+    copy_and_move_impl<MoveAndCopyOperations::CopyConstructor>(rhs);
 }
 
 template <typename T, uint64_t CAPACITY>
 inline FixedPositionContainer<T, CAPACITY>::FixedPositionContainer(FixedPositionContainer&& rhs) noexcept
 {
-    copy_and_move_impl<detail::MoveAndCopyOperations::MoveConstructor>(std::move(rhs));
+    copy_and_move_impl<MoveAndCopyOperations::MoveConstructor>(std::move(rhs));
 }
 
 template <typename T, uint64_t CAPACITY>
@@ -71,7 +70,7 @@ FixedPositionContainer<T, CAPACITY>::operator=(const FixedPositionContainer& rhs
 {
     if (this != &rhs)
     {
-        copy_and_move_impl<detail::MoveAndCopyOperations::CopyAssignment>(rhs);
+        copy_and_move_impl<MoveAndCopyOperations::CopyAssignment>(rhs);
     }
     return *this;
 }
@@ -82,20 +81,20 @@ FixedPositionContainer<T, CAPACITY>::operator=(FixedPositionContainer&& rhs) noe
 {
     if (this != &rhs)
     {
-        copy_and_move_impl<detail::MoveAndCopyOperations::MoveAssignment>(std::move(rhs));
+        copy_and_move_impl<MoveAndCopyOperations::MoveAssignment>(std::move(rhs));
     }
     return *this;
 }
 
 template <typename T, uint64_t CAPACITY>
-template <detail::MoveAndCopyOperations Opt, typename RhsType>
+template <MoveAndCopyOperations Opt, typename RhsType>
 inline void FixedPositionContainer<T, CAPACITY>::copy_and_move_impl(RhsType&& rhs) noexcept
 {
     // alias helper struct
-    using Helper = detail::MoveAndCopyHelper<Opt>;
+    using Helper = MoveAndCopyHelper<Opt>;
 
-    constexpr bool is_ctor = Helper::is_ctor();
-    constexpr bool is_move = Helper::is_move();
+    constexpr bool is_ctor = Helper::is_ctor;
+    constexpr bool is_move = Helper::is_move;
 
     // status array is not yet initialized for constructor creation
     if constexpr (is_ctor)
@@ -115,27 +114,13 @@ inline void FixedPositionContainer<T, CAPACITY>::copy_and_move_impl(RhsType&& rh
         {
             // When the slot is in the 'USED' state, it is safe to proceed with either construction (ctor) or assignment
             // operation. Therefore, creation can be carried out according to the option specified by Opt.
-            if constexpr (is_move)
-            {
-                Helper::transfer(m_data[i], std::move(*rhs_it));
-            }
-            else
-            {
-                Helper::transfer(m_data[i], *rhs_it);
-            }
+            Helper::transfer(m_data[i], Helper::move_or_copy_it(rhs_it));
         }
         else
         {
             // When the slot is in the 'FREE' state, it is unsafe to proceed with assignment operation.
             // Therefore, we need to force helper to use ctor create to make sure that the 'FREE' slots get initialized.
-            if constexpr (is_move)
-            {
-                Helper::ctor_create(m_data[i], std::move(*rhs_it));
-            }
-            else
-            {
-                Helper::ctor_create(m_data[i], *rhs_it);
-            }
+            Helper::create_new(m_data[i], Helper::move_or_copy_it(rhs_it));
         }
 
         m_status[i] = SlotStatus::USED;
diff --git a/iceoryx_dust/container/include/iox/detail/fixed_position_container_helper.hpp b/iceoryx_dust/container/include/iox/detail/fixed_position_container_helper.hpp
deleted file mode 100644
index 76ff0de14a..0000000000
--- a/iceoryx_dust/container/include/iox/detail/fixed_position_container_helper.hpp
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright (c) 2023 by Dennis Liu <dennis48161025@gmail.com>. All rights reserved. reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// SPDX-License-Identifier: Apache-2.0
-
-#ifndef IOX_DUST_CONTAINER_DETAIL_FIXED_POSITION_CONTAINER_HELPER_HPP
-#define IOX_DUST_CONTAINER_DETAIL_FIXED_POSITION_CONTAINER_HELPER_HPP
-
-#include <functional>
-#include <utility>
-
-namespace iox
-{
-namespace detail
-{
-
-enum class MoveAndCopyOperations
-{
-    CopyConstructor,
-    CopyAssignment,
-    MoveConstructor,
-    MoveAssignment,
-};
-
-/// @brief MoveAndCopyHelper is a template structure used to create or assign objects based on the provided
-/// operation type (Opt).
-/// @tparam Opt The operation type that determines how objects are created or assigned.
-template <MoveAndCopyOperations Opt>
-struct MoveAndCopyHelper
-{
-    /// @brief Creates or assigns an object to 'dest' based on the specail operation type.
-    /// @tparam T The type of the object to be created or assigned.
-    /// @tparam V The type of the source object, kept as a universal reference to preserve its lvalue or rvalue nature.
-    /// @param[out] dest The destination object where the new object is created or to which the source object is
-    /// assigned.
-    /// @param[in] src The source object, either for copy or move operations.
-    template <typename T, typename V>
-    static inline void transfer(T& dest, V&& src) noexcept
-    {
-        if constexpr (is_ctor())
-        {
-            ctor_create(dest, std::forward<V>(src));
-        }
-        else
-        {
-            assignment_create(dest, std::forward<V>(src));
-        }
-    }
-
-    /// @brief Force to use constructor to create an object at the destination.
-    /// @tparam T The type of the object to be constructed.
-    /// @tparam V The type of the source object, used for move or copy construction.
-    /// @param[out] dest The destination object where the new object is constructed.
-    /// @param[in] src The source object, either for move or copy construction.
-    template <typename T, typename V>
-    static inline void ctor_create(T& dest, V&& src) noexcept
-    {
-        if constexpr (is_move())
-        {
-            static_assert(std::is_rvalue_reference_v<decltype(src)>, "src should be rvalue reference");
-            static_assert(std::is_convertible_v<V, T>, "src type is not convertible to dest type");
-            new (&dest) T(std::forward<V>(src));
-        }
-        else
-        {
-            static_assert(std::is_lvalue_reference_v<decltype(src)>, "src should be lvalue reference");
-            static_assert(std::is_const_v<std::remove_reference_t<decltype(src)>>, "src should has 'const' modifier");
-            static_assert(std::is_convertible_v<V, T>, "src type is not convertible to dest type");
-            new (&dest) T(src);
-        }
-    }
-
-    /// @brief Force to use assignment to assign an object to the destination.
-    /// @tparam T The type of the destination object.
-    /// @tparam V The type of the source object, used for move or copy assignment.
-    /// @param dest The destination object where the source object is assigned.
-    /// @param src The source object, either for move or copy assignment.
-    template <typename T, typename V>
-    static inline void assignment_create(T& dest, V&& src) noexcept
-    {
-        if constexpr (is_move())
-        {
-            static_assert(std::is_rvalue_reference_v<decltype(src)>, "src should be rvalue reference");
-            dest = std::forward<V>(src);
-        }
-        else
-        {
-            static_assert(std::is_lvalue_reference_v<decltype(src)>, "src should be lvalue reference");
-            static_assert(std::is_const_v<std::remove_reference_t<decltype(src)>>, "src should has 'const' modifier");
-            dest = src;
-        }
-    }
-
-    /// @brief Checks if the current special operation is a constructor call.
-    /// @return True if the operation is a copy or move constructor, false otherwise.
-    static constexpr bool is_ctor() noexcept
-    {
-        return Opt == MoveAndCopyOperations::CopyConstructor || Opt == MoveAndCopyOperations::MoveConstructor;
-    }
-
-    /// @brief Checks if the current special operation is a move operation.
-    /// @return True if the operation is a move constructor or move assignment, false otherwise.
-    static constexpr bool is_move() noexcept
-    {
-        return Opt == MoveAndCopyOperations::MoveAssignment || Opt == MoveAndCopyOperations::MoveConstructor;
-    }
-};
-} // namespace detail
-} // namespace iox
-#endif
diff --git a/iceoryx_dust/container/include/iox/fixed_position_container.hpp b/iceoryx_dust/container/include/iox/fixed_position_container.hpp
index 733d0f3599..5f2473c163 100644
--- a/iceoryx_dust/container/include/iox/fixed_position_container.hpp
+++ b/iceoryx_dust/container/include/iox/fixed_position_container.hpp
@@ -19,7 +19,7 @@
 
 #include "iceoryx_hoofs/cxx/requires.hpp"
 #include "iox/algorithm.hpp"
-#include "iox/detail/fixed_position_container_helper.hpp"
+#include "iox/move_and_copy_helper.hpp"
 #include "iox/uninitialized_array.hpp"
 
 #include <cstdint>
@@ -316,7 +316,7 @@ class FixedPositionContainer final
     };
 
   private:
-    template <detail::MoveAndCopyOperations Opt, typename RhsType>
+    template <MoveAndCopyOperations Opt, typename RhsType>
     void copy_and_move_impl(RhsType&& rhs) noexcept;
 
   private:
diff --git a/iceoryx_hoofs/design/include/iox/detail/move_and_copy_helper.inl b/iceoryx_hoofs/design/include/iox/detail/move_and_copy_helper.inl
new file mode 100644
index 0000000000..7d24d67be3
--- /dev/null
+++ b/iceoryx_hoofs/design/include/iox/detail/move_and_copy_helper.inl
@@ -0,0 +1,74 @@
+// Copyright (c) 2023 by Dennis Liu <dennis48161025@gmail.com>. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: Apache-2.0
+
+#ifndef IOX_HOOFS_DESIGN_MOVE_AND_COPY_HELPER_INL
+#define IOX_HOOFS_DESIGN_MOVE_AND_COPY_HELPER_INL
+
+#include "iox/move_and_copy_helper.hpp"
+
+namespace iox
+{
+template <MoveAndCopyOperations Opt>
+template <typename T, typename V>
+inline void MoveAndCopyHelper<Opt>::transfer(T& dest, V&& src) noexcept
+{
+    if constexpr (is_ctor)
+    {
+        create_new(dest, std::forward<V>(src));
+    }
+    else
+    {
+        assign(dest, std::forward<V>(src));
+    }
+}
+
+template <MoveAndCopyOperations Opt>
+template <typename T, typename V>
+inline void MoveAndCopyHelper<Opt>::create_new(T& dest, V&& src) noexcept
+{
+    if constexpr (is_move)
+    {
+        static_assert(std::is_rvalue_reference_v<decltype(src)>, "src should be rvalue reference");
+        static_assert(std::is_convertible_v<V, T>, "src type is not convertible to dest type");
+        new (&dest) T(std::forward<V>(src));
+    }
+    else
+    {
+        static_assert(std::is_lvalue_reference_v<decltype(src)>, "src should be lvalue reference");
+        static_assert(std::is_const_v<std::remove_reference_t<decltype(src)>>, "src should have 'const' modifier");
+        static_assert(std::is_convertible_v<V, T>, "src type is not convertible to dest type");
+        new (&dest) T(src);
+    }
+}
+
+template <MoveAndCopyOperations Opt>
+template <typename T, typename V>
+inline void MoveAndCopyHelper<Opt>::assign(T& dest, V&& src) noexcept
+{
+    if constexpr (is_move)
+    {
+        static_assert(std::is_rvalue_reference_v<decltype(src)>, "src should be rvalue reference");
+        dest = std::forward<V>(src);
+    }
+    else
+    {
+        static_assert(std::is_lvalue_reference_v<decltype(src)>, "src should be lvalue reference");
+        static_assert(std::is_const_v<std::remove_reference_t<decltype(src)>>, "src should have 'const' modifier");
+        dest = src;
+    }
+}
+} // namespace iox
+#endif
diff --git a/iceoryx_hoofs/design/include/iox/move_and_copy_helper.hpp b/iceoryx_hoofs/design/include/iox/move_and_copy_helper.hpp
new file mode 100644
index 0000000000..34bae27661
--- /dev/null
+++ b/iceoryx_hoofs/design/include/iox/move_and_copy_helper.hpp
@@ -0,0 +1,167 @@
+// Copyright (c) 2023 by Dennis Liu <dennis48161025@gmail.com>. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: Apache-2.0
+
+#ifndef IOX_HOOFS_DESIGN_MOVE_AND_COPY_HELPER_HPP
+#define IOX_HOOFS_DESIGN_MOVE_AND_COPY_HELPER_HPP
+
+#include <functional>
+#include <utility>
+
+namespace iox
+{
+
+enum class MoveAndCopyOperations
+{
+    CopyConstructor,
+    CopyAssignment,
+    MoveConstructor,
+    MoveAssignment,
+};
+
+/// @brief MoveAndCopyHelper is a template structure used to create or assign objects based on the provided
+/// operation type (Opt). All of methods in this class are general for MoveAndCopyOperations. Any function that depends
+/// on specific MoveAndCopyOperations should move to partial specialization region.
+/// @tparam Opt The operation type that determines how objects are created or assigned.
+template <MoveAndCopyOperations Opt>
+class MoveAndCopyHelper
+{
+  public:
+    static constexpr bool is_ctor =
+        Opt == MoveAndCopyOperations::CopyConstructor || Opt == MoveAndCopyOperations::MoveConstructor;
+    static constexpr bool is_move =
+        Opt == MoveAndCopyOperations::MoveAssignment || Opt == MoveAndCopyOperations::MoveConstructor;
+
+  public:
+    /// @brief Creates or assigns an object to 'dest' based on the specail operation type.
+    /// @tparam T The type of the object to be created or assigned.
+    /// @tparam V The type of the source object, kept as a universal reference to preserve its lvalue or rvalue nature.
+    /// @param[out] dest The destination object where the new object is created or to which the source object is
+    /// assigned.
+    /// @param[in] src The source object, either for copy or move operations.
+    template <typename T, typename V>
+    static void transfer(T& dest, V&& src) noexcept;
+
+    /// @brief Force to use constructor to create an object at the destination.
+    /// @tparam T The type of the object to be constructed.
+    /// @tparam V The type of the source object, used for move or copy construction.
+    /// @param[out] dest The destination object where the new object is constructed.
+    /// @param[in] src The source object, either for move or copy construction.
+    template <typename T, typename V>
+    static void create_new(T& dest, V&& src) noexcept;
+
+    /// @brief Force to use assignment to assign an object to the destination.
+    /// @tparam T The type of the destination object.
+    /// @tparam V The type of the source object, used for move or copy assignment.
+    /// @param dest The destination object where the source object is assigned.
+    /// @param src The source object, either for move or copy assignment.
+    template <typename T, typename V>
+    static void assign(T& dest, V&& src) noexcept;
+
+    /// @brief Moves a value if the condition specified by 'enable_if_t' is met.
+    /// @details This overload of 'move_or_copy' is enabled when 'Opt' is either 'MoveAssignment' or 'MoveConstructor'.
+    ///          It moves the given value, providing an efficient way to transfer resources.
+    /// @tparam T The type of the value to be moved.
+    /// @tparam enable_if A SFINAE condition that enables this overload for move operations.
+    /// @param[in] src The source value to be moved.
+    /// @return A reference to the moved value.
+    /// @note This overload is selected when the template parameter 'Opt' indicates a move operation.
+    /// @note We use std::remove_reference_t<T>&& as return type for 'T' might be a lvalue reference (for struct)
+    /// @example
+    /// An example of simplifying the usage of 'if constexpr' branches in a loop.
+    /// The original code:
+    /// \code{.cpp}
+    /// for (uint64_t i = 0; i < rhs.size(); ++i)
+    /// {
+    ///     if constexpr (is_move)
+    ///     {
+    ///         Helper::transfer(m_data[i], std::move(rhs.data[i]));
+    ///     }
+    ///     else
+    ///     {
+    ///         Helper::transfer(m_data[i], rhs.data[i]);
+    ///     }
+    /// }
+    /// \endcode
+    /// can be simplified to:
+    /// \code{.cpp}
+    /// for (uint64_t i = 0; i < rhs.size(); ++i)
+    /// {
+    ///     Helper::transfer(m_data[i], Helper::move_or_copy(rhs.data[i]));
+    /// }
+    /// \endcode
+    template <typename T, typename = std::enable_if_t<is_move, T>>
+    static inline std::remove_reference_t<T>&& move_or_copy(T&& src) noexcept
+    {
+        static_assert(is_move, "is_move should be true");
+        return std::move(std::forward<T>(src));
+    }
+
+    /// @brief Copies a value if the condition specified by 'enable_if_t' is not met for move operations.
+    /// @details This overload of 'move_or_copy' is enabled for cases other than 'MoveAssignment' or 'MoveConstructor'.
+    ///          It simply copies the given value.
+    /// @tparam T The type of the value to be copied.
+    /// @tparam enable_if A SFINAE condition that enables this overload for copy operations.
+    /// @param[in] src The source value to be copied.
+    /// @return A const reference to the copied value.
+    /// @note This overload is selected when the template parameter 'Opt' does not indicate a move operation.
+    template <typename T, typename = std::enable_if_t<!is_move, T>>
+    static inline const T& move_or_copy(const T& src) noexcept
+    {
+        static_assert(!is_move, "is_move should be false");
+        return src;
+    }
+
+    /// @brief Moves a value pointed by an iterator if the condition specified by 'enable_if_t' is met.
+    /// @details This overload of 'move_or_copy_it' is enabled when 'Opt' is either 'MoveAssignment' or
+    /// 'MoveConstructor'.
+    ///          It moves the value pointed by the given iterator.
+    /// @tparam Iterator The type of the iterator.
+    /// @tparam enable_if A SFINAE condition that enables this overload for move operations.
+    /// @param[in] it The iterator pointing to the value to be moved.
+    /// @return A moved value from the iterator's pointee.
+    /// @note This overload is selected for move operations based on 'Opt'.
+    /// @note If the decltype syntax missed, move ctor will be called twice
+    template <typename Iterator, typename = std::enable_if_t<is_move, Iterator>>
+    static inline auto move_or_copy_it(Iterator& it) noexcept -> std::remove_reference_t<decltype(*it)>&&
+    {
+        static_assert(is_move, "is_move should be true");
+        return std::move(*it);
+    }
+
+    /// @brief Accesses a value pointed by an iterator if the condition specified by 'enable_if_t' is not met for move
+    /// operations.
+    /// @details This overload of 'move_or_copy_it' is enabled for cases other than 'MoveAssignment' or
+    /// 'MoveConstructor'.
+    ///          It provides direct access to the value pointed by the iterator.
+    /// @tparam Iterator The type of the iterator.
+    /// @tparam enable_if A SFINAE condition that enables this overload for direct access operations.
+    /// @param[in] it The iterator pointing to the value to be accessed.
+    /// @return A direct access to the value from the iterator's pointee.
+    /// @note This overload is selected for direct access operations when 'Opt' does not indicate a move operation.
+    /// @note If the decltype syntax missed, move assignment will be called twice
+    template <typename Iterator, typename = std::enable_if_t<!is_move, Iterator>>
+    static inline auto move_or_copy_it(Iterator& it) noexcept -> const decltype(*it)&
+    {
+        static_assert(!is_move, "is_move should be false");
+        return *it;
+    }
+};
+
+} // namespace iox
+
+#include "iox/detail/move_and_copy_helper.inl"
+
+#endif