c++ - 如何正确地将转换构造函数从 std::queue 传递到底层 std::deque?

标签 c++ c++11 memory-management stl

我创建了一个自定义内存分配器。为了将其与 STL 容器一起使用,我还创建了一个包装器,以便它遵循 std::allocator_traits要求。

#include <cstdint>
#include <memory>
#include <deque>
#include <queue>

class CustomAlloc
{
public:
    CustomAlloc(const std::size_t& maxMem) noexcept
    :
        m_maxMem(maxMem),
        m_usedMem(0)
    {

    }

    CustomAlloc(CustomAlloc&& other) noexcept
    :
        m_maxMem(other.m_maxMem),
        m_usedMem(other.m_usedMem)
    {

    }

    CustomAlloc& operator=(CustomAlloc&& other) noexcept
    {
        m_maxMem = other.m_maxMem;
        m_usedMem = other.m_usedMem;
        return *this;
    }

    CustomAlloc(const CustomAlloc&) = delete;
    CustomAlloc& operator=(CustomAlloc&) = delete;

    [[nodiscard]] void* Allocate(const std::size_t& size)
    {
        if(m_usedMem + size > m_maxMem)
        {
            throw std::bad_alloc();
        }

        void* ptr = std::malloc(size);

        if(ptr == nullptr)
        {
            throw std::bad_alloc();
        }

        m_usedMem += size;

        return ptr;
    }

    void Free(void* const ptr) const
    {
        return std::free(ptr);
    }

    const std::size_t& GetMaxMem() const noexcept
    {
        return m_maxMem;
    }

private:
    std::size_t m_maxMem;
    std::size_t m_usedMem;
};

template<typename T, typename Alloc>
class STLAdaptor
{
public:

    typedef T value_type;

    STLAdaptor(Alloc& allocator) noexcept
    :
        m_allocator(allocator)
    {

    }

    template<typename U>
    STLAdaptor(const STLAdaptor<U, Alloc>& other) noexcept
    :
        m_allocator(other.m_allocator)
    {}

    [[nodiscard]] constexpr T* allocate(std::size_t n)
    {
        return reinterpret_cast<T*>
            (m_allocator.Allocate(n * sizeof(T)));
    }

    constexpr void deallocate(T* p, [[maybe_unused]] std::size_t n)
    {
        m_allocator.Free(p);
    }

    std::size_t MaxAllocationSize() const
    {
        return m_allocator.GetMaxMem();
    }

    bool operator==(const STLAdaptor<T,Alloc>& rhs)
    {
        return m_allocator.GetStart() == rhs.m_allocator.GetStart();
    }

    bool operator!=(const STLAdaptor<T,Alloc>& rhs)
    {
        return !(*this == rhs);
    }

    Alloc& m_allocator;
};

template<typename T, typename Alloc>
using CustomDeque = std::deque<T, STLAdaptor<T,Alloc>>;

template<typename T, typename Alloc>
using CustomQueue = std::queue<T, CustomDeque<T, Alloc>>;

我面临的问题:

int main()
{
    CustomAlloc customAlloc(3000000);

    CustomDeque<int, CustomAlloc> customDeque(customAlloc);

    CustomQueue<int, CustomAlloc> customQueue(STLAdaptor<int, CustomAlloc>{customAlloc});

    return 0;
}

这工作得很好,但是必须传递 STLAdaptor<int, CustomAlloc>{customAlloc} 是代码错误。其中所有其他 STL 容器都可以依赖 STLAdaptor 的转换构造函数。 .

我想做的是:

int main()
{
    CustomAlloc customAlloc(3000000);

    CustomDeque<int, CustomAlloc> customDeque(customAlloc);

    CustomQueue<int, CustomAlloc> customQueue(customAlloc);

    return 0;
}

哪里customAlloc以某种方式传递给底层 std::deque .

最佳答案

如果您无法按照 Ted Lyngmo 的建议更改 CustomAlloc 代码,则替代方法是将 CustomQueue 定义为 std::queue 的子类:

template<typename T, typename Alloc>
struct CustomQueue : std::queue<T, CustomDeque<T, Alloc>>
{
    CustomQueue(Alloc& alloc) :std::queue<T, CustomDeque<T, Alloc>>(STLAdaptor<T, Alloc>(alloc)) {}
};

现在您可以通过仅传递分配器来构造它:

int main()
{
    CustomAlloc customAlloc(3000000);

    CustomDeque<int, CustomAlloc> customDeque(customAlloc);

    CustomQueue<int, CustomAlloc> customQueue(customAlloc);

    customQueue.push(5);

    return 0;
}

此代码已在 VS 2019 上测试。

关于c++ - 如何正确地将转换构造函数从 std::queue 传递到底层 std::deque?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71746147/

相关文章:

c++ - 用 C++ 编写符合 IEEE-754 标准的双/浮点除法的最快方法是什么?

c++ - 登录网站,然后访问该网站的另一部分

c++ - 为什么通过 weak_ptr 调用这么慢?

asp.net - HttpContext.Cache物理内存使用情况

python - 垃圾收集器是否跟踪所有 Python 对象?

c++ - 在 Switch 语句中声明变量

c++ - 使用 Opencv 调整/裁剪图像

c++ - c++11 中只有 std::mt19937 的实例重复值

c++ - 递归定义的嵌套类型(就不完整类型而言)

c++ - 为最终的 future 自定义内存分配器做准备