Some work on maybe_uninit & option
This commit is contained in:
@ -9,15 +9,3 @@
|
|||||||
#else
|
#else
|
||||||
#define ASL_NO_UNIQUE_ADDRESS [[no_unique_address]]
|
#define ASL_NO_UNIQUE_ADDRESS [[no_unique_address]]
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace asl
|
|
||||||
{
|
|
||||||
|
|
||||||
struct unsafe
|
|
||||||
{
|
|
||||||
unsafe() = delete;
|
|
||||||
explicit unsafe(auto&&) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace asl
|
|
||||||
|
|
||||||
|
@ -1,42 +1,61 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "asl/annotations.hpp"
|
|
||||||
#include "asl/layout.hpp"
|
#include "asl/layout.hpp"
|
||||||
#include "asl/memory.hpp"
|
#include "asl/memory.hpp"
|
||||||
#include "asl/meta.hpp"
|
#include "asl/meta.hpp"
|
||||||
|
#include "asl/utility.hpp"
|
||||||
|
|
||||||
namespace asl
|
namespace asl
|
||||||
{
|
{
|
||||||
|
|
||||||
template<is_object T>
|
template<is_object T>
|
||||||
class alignas(align_of<T>) maybe_uninit
|
class maybe_uninit
|
||||||
{
|
{
|
||||||
char m_storage[size_of<T>];
|
union
|
||||||
|
{
|
||||||
|
alignas(align_of<T>) char m_storage[size_of<T>];
|
||||||
|
T m_value;
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr void* uninit_ptr() const { return m_storage; }
|
constexpr maybe_uninit() {} // NOLINT(*-member-init)
|
||||||
|
|
||||||
|
maybe_uninit(const maybe_uninit&) = delete;
|
||||||
|
maybe_uninit(maybe_uninit&&) = delete;
|
||||||
|
|
||||||
|
maybe_uninit& operator=(const maybe_uninit&) = delete;
|
||||||
|
maybe_uninit& operator=(maybe_uninit&&) = delete;
|
||||||
|
|
||||||
|
constexpr ~maybe_uninit() = default;
|
||||||
|
constexpr ~maybe_uninit() requires (!trivially_destructible<T>) {}
|
||||||
|
|
||||||
|
constexpr void* uninit_ptr() && = delete;
|
||||||
|
constexpr const void* uninit_ptr() const& { return m_storage; }
|
||||||
|
constexpr void* uninit_ptr() & { return m_storage; }
|
||||||
|
|
||||||
// @Safety Pointer must only be accessed when in initialized state.
|
// @Safety Pointer must only be accessed when in initialized state.
|
||||||
constexpr const T* init_ptr(unsafe) const { return reinterpret_cast<const T*>(m_storage); }
|
constexpr T* init_ptr_unsafe() && = delete;
|
||||||
constexpr T* init_ptr(unsafe) { return reinterpret_cast< T*>(m_storage); }
|
constexpr const T* init_ptr_unsafe() const& { return &m_value; }
|
||||||
|
constexpr T* init_ptr_unsafe() & { return &m_value; }
|
||||||
|
|
||||||
// @Safety Reference must only be accessed when in initialized state.
|
// @Safety Reference must only be accessed when in initialized state.
|
||||||
constexpr const T& as_init(unsafe) const { return *reinterpret_cast<const T*>(m_storage); }
|
constexpr T& as_init_unsafe() && = delete;
|
||||||
constexpr T& as_init(unsafe) { return *reinterpret_cast< T*>(m_storage); }
|
constexpr const T& as_init_unsafe() const& { return m_value; }
|
||||||
|
constexpr T& as_init_unsafe() & { return m_value; }
|
||||||
|
|
||||||
// @Safety Must be called only when in uninitialized state.
|
// @Safety Must be called only when in uninitialized state.
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
inline void init(unsafe, Args&&... args)
|
constexpr void init_unsafe(Args&&... args) &
|
||||||
{
|
{
|
||||||
new(uninit_ptr()) T(ASL_FWD(args)...);
|
new(uninit_ptr()) T(ASL_FWD(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Safety Must be called only when in initialized state.
|
// @Safety Must be called only when in initialized state.
|
||||||
inline void uninit(unsafe)
|
constexpr void uninit_unsafe() &
|
||||||
{
|
{
|
||||||
if constexpr (!trivially_destructible<T>)
|
if constexpr (!trivially_destructible<T>)
|
||||||
{
|
{
|
||||||
init_ptr(unsafe("Caller has checked init state"))->~T();
|
init_ptr_unsafe()->~T();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,14 @@
|
|||||||
#include "asl/maybe_uninit.hpp"
|
#include "asl/maybe_uninit.hpp"
|
||||||
|
#include "asl/test_types.hpp"
|
||||||
|
|
||||||
static_assert(asl::layout::of<int>() == asl::layout::of<asl::maybe_uninit<int>>());
|
static_assert(asl::layout::of<int>() == asl::layout::of<asl::maybe_uninit<int>>());
|
||||||
static_assert(asl::size_of<int> == asl::size_of<asl::maybe_uninit<int>>);
|
static_assert(asl::size_of<int> == asl::size_of<asl::maybe_uninit<int>>);
|
||||||
static_assert(asl::align_of<int> == asl::align_of<asl::maybe_uninit<int>>);
|
static_assert(asl::align_of<int> == asl::align_of<asl::maybe_uninit<int>>);
|
||||||
|
|
||||||
int main() { return 0; }
|
static_assert(asl::trivially_destructible<asl::maybe_uninit<TriviallyDestructible>>);
|
||||||
|
static_assert(!asl::trivially_destructible<asl::maybe_uninit<HasDestructor>>);
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -1,13 +1,30 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "asl/meta.hpp"
|
#include "asl/meta.hpp"
|
||||||
|
#include "asl/maybe_uninit.hpp"
|
||||||
|
|
||||||
namespace asl
|
namespace asl
|
||||||
{
|
{
|
||||||
|
|
||||||
|
struct nullopt_t {};
|
||||||
|
static constexpr nullopt_t nullopt{};
|
||||||
|
|
||||||
template<is_object T>
|
template<is_object T>
|
||||||
class option
|
class option
|
||||||
{
|
{
|
||||||
|
maybe_uninit<T> m_payload;
|
||||||
|
bool m_has_value = false;
|
||||||
|
|
||||||
|
public:
|
||||||
|
constexpr option() = default;
|
||||||
|
constexpr option(nullopt_t) {} // NOLINT(*-explicit-conversions)
|
||||||
|
|
||||||
|
constexpr ~option() = default;
|
||||||
|
constexpr ~option() requires (!trivially_destructible<T>)
|
||||||
|
{
|
||||||
|
if (m_has_value) { m_payload.uninit_unsafe(); }
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace asl
|
} // namespace asl
|
||||||
|
@ -1,3 +1,12 @@
|
|||||||
#include "asl/option.hpp"
|
#include "asl/option.hpp"
|
||||||
|
#include "asl/test_types.hpp"
|
||||||
|
|
||||||
int main() { return 0; }
|
static_assert(asl::trivially_destructible<asl::option<TriviallyDestructible>>);
|
||||||
|
static_assert(!asl::trivially_destructible<asl::option<HasDestructor>>);
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
asl::option<HasDestructor> a;
|
||||||
|
asl::option<TriviallyDestructible> b;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user