如何正确地将转换构造函数从 std::queue 传递到基础 std::deque?

How do I correctly pass converting constructor from an std::queue through to the underlying std::deque?

我已经创建了一个自定义内存分配器。为了将它与 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 上测试。