psemek/libs/wgpu/include/psemek/wgpu/chained_struct.hpp

81 lines
1.6 KiB
C++

#pragma once
#include <memory>
#include <vector>
namespace psemek::wgpu
{
struct chained_struct;
namespace detail
{
struct chained_struct_base
{
virtual ~chained_struct_base() {}
virtual void * ptr() = 0;
};
struct empty_storage
{};
template <typename ChainedType, typename StorageType>
struct chained_struct_impl
: chained_struct_base
{
chained_struct_impl(ChainedType const & chained, StorageType const & storage)
: chained_(chained)
, storage_(std::move(storage))
{}
chained_struct_impl(ChainedType const & chained, StorageType && storage)
: chained_(chained)
, storage_(std::move(storage))
{}
void * ptr() override
{
return &chained_;
}
private:
ChainedType chained_;
StorageType storage_;
};
void * fill_chain(std::vector<chained_struct> const & chain);
using chained_struct_ptr = std::shared_ptr<chained_struct_base>;
template <typename ChainedType>
chained_struct_ptr make_chained_struct(ChainedType const & chained)
{
return std::make_shared<chained_struct_impl<ChainedType, empty_storage>>(chained, empty_storage{});
}
template <typename ChainedType, typename StorageType>
chained_struct_ptr make_chained_struct(ChainedType const & chained, StorageType && storage)
{
return std::make_shared<chained_struct_impl<ChainedType, std::remove_cvref_t<StorageType>>>(chained, std::forward<StorageType>(storage));
}
}
struct chained_struct
{
template <typename T>
chained_struct(T const & value)
: impl_(to_chained_struct(value))
{}
void * ptr() const
{
return impl_->ptr();
}
private:
detail::chained_struct_ptr impl_;
};
}