Files
botw/lib/sead/include/prim/seadStorageFor.h
T
Léo Lam 18c60323a9 Switch to subrepos
git subrepo clone https://github.com/open-ead/sead lib/sead

subrepo:
  subdir:   "lib/sead"
  merged:   "1b66e825d"
upstream:
  origin:   "https://github.com/open-ead/sead"
  branch:   "master"
  commit:   "1b66e825d"
git-subrepo:
  version:  "0.4.3"
  origin:   "https://github.com/ingydotnet/git-subrepo"
  commit:   "2f68596"

git subrepo clone (merge) https://github.com/open-ead/nnheaders lib/NintendoSDK

subrepo:
  subdir:   "lib/NintendoSDK"
  merged:   "9ee21399f"
upstream:
  origin:   "https://github.com/open-ead/nnheaders"
  branch:   "master"
  commit:   "9ee21399f"
git-subrepo:
  version:  "0.4.3"
  origin:   "ssh://git@github.com/ingydotnet/git-subrepo"
  commit:   "2f68596"

git subrepo clone https://github.com/open-ead/agl lib/agl

subrepo:
  subdir:   "lib/agl"
  merged:   "7c063271b"
upstream:
  origin:   "https://github.com/open-ead/agl"
  branch:   "master"
  commit:   "7c063271b"
git-subrepo:
  version:  "0.4.3"
  origin:   "ssh://git@github.com/ingydotnet/git-subrepo"
  commit:   "2f68596"

git subrepo clone https://github.com/open-ead/EventFlow lib/EventFlow

subrepo:
  subdir:   "lib/EventFlow"
  merged:   "c35d21b34"
upstream:
  origin:   "https://github.com/open-ead/EventFlow"
  branch:   "master"
  commit:   "c35d21b34"
git-subrepo:
  version:  "0.4.3"
  origin:   "ssh://git@github.com/ingydotnet/git-subrepo"
  commit:   "2f68596"
2022-03-21 21:31:42 +01:00

86 lines
2.6 KiB
C++

#pragma once
#include <utility>
#include "basis/seadTypes.h"
namespace sead
{
struct InitializeTag
{
};
struct ZeroInitializeTag
{
};
/// Provides suitably aligned uninitialized storage for a type T.
/// Use this as a std::aligned_storage replacement that is easier to use and less error prone for
/// common cases (std::aligned_storage_t<sizeof(T), alignof(T)>).
template <typename T, bool AutoDestruct = false>
class StorageFor
{
public:
constexpr StorageFor() = default;
explicit StorageFor(InitializeTag) { constructDefault(); }
template <typename... Args>
explicit StorageFor(InitializeTag, Args&&... args)
{
construct(std::forward<Args>(args)...);
}
explicit StorageFor(ZeroInitializeTag) : mStorage{} { constructDefault(); }
template <typename... Args>
explicit StorageFor(ZeroInitializeTag, Args&&... args) : mStorage{}
{
construct(std::forward<Args>(args)...);
}
T* constructDefault() { return new (storage()) T; }
template <typename... Args>
T* construct(Args&&... args)
{
return new (storage()) T(std::forward<Args>(args)...);
}
~StorageFor()
{
if constexpr (AutoDestruct)
destruct();
}
/// @warning It is undefined behavior to call this if no object has been constructed.
void destruct() { data()->~T(); }
/// @warning It is undefined behavior to call this if no object has been constructed.
T& ref() { return reinterpret_cast<T&>(mStorage); }
/// @warning It is undefined behavior to call this if no object has been constructed.
const T& ref() const { return reinterpret_cast<const T&>(mStorage); }
/// @warning It is undefined behavior to call this if no object has been constructed.
T* data() { return reinterpret_cast<T*>(mStorage); }
/// @warning It is undefined behavior to call this if no object has been constructed.
const T* data() const { return reinterpret_cast<const T*>(mStorage); }
/// @warning It is undefined behavior to call this if no object has been constructed.
T* operator->() { return data(); }
/// @warning It is undefined behavior to call this if no object has been constructed.
const T* operator->() const { return data(); }
/// @warning It is undefined behavior to call this if no object has been constructed.
T& operator*() { return ref(); }
/// @warning It is undefined behavior to call this if no object has been constructed.
const T& operator*() const { return ref(); }
void* storage() { return mStorage; }
const void* storage() const { return mStorage; }
private:
alignas(T) u8 mStorage[sizeof(T)];
};
} // namespace sead