如何正确地将转换构造函数从 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 上测试。
我已经创建了一个自定义内存分配器。为了将它与 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 上测试。