Skip to content

Instantly share code, notes, and snippets.

@jeremyong
Last active September 10, 2018 06:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jeremyong/73a6e2ee012360592c3cfb95119bec82 to your computer and use it in GitHub Desktop.
Save jeremyong/73a6e2ee012360592c3cfb95119bec82 to your computer and use it in GitHub Desktop.
#pragma once
#include <vector>
#include <vulkan/vulkan.hpp>
namespace vkf
{
template <typename Type, typename Dispatch = vk::DispatchLoaderStatic>
class VkUniqueVector
{
using Container = std::vector<Type>;
using Deleter = typename vk::UniqueHandleTraits<Type, Dispatch>::deleter;
// This is being used right now because the "destroy" member function is protected and we need to access it without inheritance
struct Hack : public Deleter
{
template <typename T>
using Destroyer = void (Deleter::*)(T);
template <typename T>
static Destroyer<T> get_destroyer()
{
return &Hack::destroy;
}
};
public:
VkUniqueVector() = default;
VkUniqueVector(const VkUniqueVector&) = delete;
VkUniqueVector& operator=(const VkUniqueVector&) = delete;
VkUniqueVector(VkUniqueVector&& other)
: m_data{std::move(other.m_data)}
, m_deleters{std::move(other.m_deleters)}
{
}
VkUniqueVector& operator=(VkUniqueVector&& other)
{
if (this == &other)
{
return *this;
}
m_data = std::move(other.m_data);
m_deleters = std::move(other.m_deleters);
return *this;
}
~VkUniqueVector()
{
cleanup();
}
Type emplace_back(vk::UniqueHandle<Type, Dispatch>&& handle)
{
Type result = m_data.emplace_back(*handle);
handle.release();
m_deleters.emplace_back(std::move(static_cast<Deleter>(handle)));
return result;
}
void reserve(size_t size)
{
m_data.reserve(size);
m_deleters.reserve(size);
}
void clear()
{
cleanup();
m_data.clear();
m_deleters.clear();
}
uint32_t size() const
{
return static_cast<uint32_t>(m_data.size());
}
bool empty() const
{
return m_data.empty();
}
const Type* data() const
{
return m_data.data();
}
Type* data()
{
return m_data.data();
}
Type operator[](size_t i) const
{
return m_data[i];
}
typename Container::iterator begin()
{
return m_data.begin();
}
typename Container::iterator end()
{
return m_data.end();
}
typename Container::const_iterator begin() const
{
return m_data.cbegin();
}
typename Container::iterator end() const
{
return m_data.cend();
}
typename Container::iterator rbegin()
{
return m_data.rbegin();
}
typename Container::iterator rend()
{
return m_data.rend();
}
typename Container::iterator rbegin() const
{
return m_data.crbegin();
}
typename Container::iterator rend() const
{
return m_data.crend();
}
private:
void cleanup()
{
for (size_t i = 0; i != m_data.size(); ++i)
{
auto& deleter = m_deleters[i];
(deleter.*Hack::get_destroyer<Type>())(m_data[i]);
}
}
Container m_data;
std::vector<Deleter> m_deleters;
};
} // namespace vkf
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment