如何正确地将转换构造函数从std::queue传递到底层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}中传递代码gore,因为所有其他STL容器都可以依赖于STLAdaptor的转换构造函数。

我想做的是:

int main()
{
CustomAlloc customAlloc(3000000);
CustomDeque<int, CustomAlloc> customDeque(customAlloc);
CustomQueue<int, CustomAlloc> customQueue(customAlloc);
return 0;
}

其中CCD_ 4以某种方式被传递到底层CCD_。

如果您不能像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上进行了测试。

最新更新