Garmaine Staff asked 1 year ago

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.