I'm working on (yet another) C++ serialization library that supports standard types such as containers. In particular I want to support smart pointers.
C++17 introduced support for std::shared_ptr
holding raw arrays (it knows to invoke delete []
in such cases). I need to detect that the shared_ptr
is holding a raw array so that I can serialize it accordingly:
template <typename T>
void serialize(Writer& writer, const std::shared_ptr<T> ptr)
{
// Writer has overloaded operator()
if (ptr)
{
if (holdsRawArray(ptr)) // How to implement this???
{
auto arrayWriter = writer.array(); // RAII
auto size = rawArraySize(ptr); // How to get this???
for (std::size_t i=0; i<size; ++i)
arrayWriter(ptr[i]);
}
else
writer(*ptr);
}
else
writer(null);
}
How do I determine that a C++17 smart pointer contains a raw array? This information is erased in the element_type
member typedef (via std::remove_extent_t
). I also can't find anything in the smart pointer API that would reveal the size of the raw array.
I thought about using the detector idiom on operator[]
and operator*
, but it appears implementations are not required to undefine them if T
is or isn't a raw array.
Is what I'm attempting even possible? I'm hoping I missed something, or that there's some trick I could use.
I know I can force users to use std::shared_ptr<std::array<N,T>>
or std::shared_ptr<std::vector<T>>
instead, but I just want to check if it's even possible for me to support smart pointers holding raw arrays.
You can determine if shared_ptr
holds an array type by checking if T is an array type using compile-time type traits. It is even implemented in std.
if constexpr (std::is_array_v<T>)
But there is no way to get the size because it is allocated dynamically and not stored anywhere.