Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes PointerVector's slicing issue for polymorphic types. #1550

Merged
merged 6 commits into from
Sep 20, 2024
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions Common++/header/PointerVector.h
seladb marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <stdexcept>
#include <vector>
#include <memory>
#include <type_traits>

#include "DeprecationUtils.h"

Expand All @@ -18,6 +19,31 @@
namespace pcpp
{

namespace internal
{
/**
* @brief void_t (added officially in C++17) is a fancy trick to just instantiate stuff and then discard it
*/
template <class...> using void_t = void;

/**
* @brief A type trait that checks if a class has a clone method.
* @tparam T The class to check.
* @tparam Dummy A dummy parameter to enable SFINAE.
*/
template <class T, typename = void_t<>> struct has_clone : std::false_type
{
};

/**
* @brief A type trait that checks if a class has a clone method.
* @tparam T The class to check.
*/
template <class T> struct has_clone<T, void_t<decltype(std::declval<T>().clone())>> : std::true_type
{
};
} // namespace internal

/**
* @class PointerVector
* A template class for representing a std::vector of pointers. Once (a pointer to) an element is added to this
Expand Down Expand Up @@ -50,7 +76,9 @@ namespace pcpp
* @param[in] other The vector to copy from.
* @remarks As the vector is copied via deep copy, all pointers obtained from the copied vector
* reference the duplicates and not the originals.
* @deprecated Deprecated in favor of clone()
*/
PCPP_DEPRECATED("Deprecated in favor of clone()")
PointerVector(const PointerVector& other) : m_Vector(deepCopyUnsafe(other.m_Vector))
{}

Expand All @@ -76,7 +104,9 @@ namespace pcpp
* See copy constructor for more information on the specific copy procedure.
* @param[in] other The vector to copy from.
* @return A reference to the current object.
* @deprecated Deprecated in favor of clone()
*/
PCPP_DEPRECATED("Deprecated in favor of clone()")
PointerVector& operator=(const PointerVector& other)
{
// Saves a copy of the old pointer to defer cleanup.
Expand Down Expand Up @@ -334,6 +364,40 @@ namespace pcpp
return m_Vector.at(index);
}

template <class E = T, typename std::enable_if<std::is_polymorphic<E>::value && !internal::has_clone<E>::value,
bool>::type = false>
PointerVector<T> clone() const = delete;

/**
* @brief Makes a deep copy of the pointer vector.
* @return A copy of the vector with all elements duplicated.
* @remarks This overload is used when the elements are polymorphic and have a clone method.
*/
template <class E = T, typename std::enable_if<std::is_polymorphic<E>::value && internal::has_clone<E>::value,
bool>::type = false>
PointerVector<T> clone() const
{
PointerVector<T> clone;
for (const auto iter : m_Vector)
{
clone.pushBack(std::move(iter->clone()));
}
return clone;
}

/**
* @brief Makes a deep copy of the pointer vector.
* @return A copy of the vector with all elements duplicated.
* @remarks This overload is used when the elements are not polymorphic.
*/
template <class E = T, typename std::enable_if<!std::is_polymorphic<E>::value, bool>::type = false>
PointerVector<T> clone() const
{
PointerVector<T> clone;
clone.m_Vector = std::move(deepCopyUnsafe(m_Vector));
return clone;
}

private:
/**
* Performs a copy of the vector along with its elements.
Expand Down
Loading