81 lines
1.6 KiB
C++
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_;
|
|
};
|
|
|
|
}
|