首页 > 解决方案 > 检测 std::shared_ptr 是否持有原始数组(并获取其大小)

问题描述

我正在开发(又一个)支持标准类型(如容器)的 C++ 序列化库。特别是我想支持智能指针。

C++17 引入了对std::shared_ptr保存原始数组的支持(它知道在这种情况下调用delete [])。我需要检测到shared_ptr它持有一个原始数组,以便我可以相应地对其进行序列化:

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);
}

如何确定 C++17 智能指针包含原始数组?此信息在element_type成员 typedef 中删除(通过std::remove_extent_t)。我在智能指针 API 中也找不到任何可以显示原始数组大小的东西。

我考虑过在 and 上使用检测器习语operator[],但如果是或不是原始数组operator*,似乎不需要实现来取消定义它们。T

我正在尝试的甚至可能吗?我希望我错过了一些东西,或者我可以使用一些技巧。

我知道我可以强制用户使用std::shared_ptr<std::array<N,T>>orstd::shared_ptr<std::vector<T>>代替,但我只想检查我是否有可能支持保存原始数组的智能指针。

标签: c++arraysc++17shared-ptrsmart-pointers

解决方案


您可以shared_ptr通过使用编译时类型特征检查 T 是否为数组类型来确定是否包含数组类型。它甚至在标准中实现。

if constexpr (std::is_array_v<T>)

但是没有办法获得大小,因为它是动态分配的,而不是存储在任何地方。


推荐阅读