Orange/include/Orange/Core/Result.h

82 lines
2.1 KiB
C++

#pragma once
#include <Orange/Core/Log.h>
#include <Orange/Core/AlignedStorage.h>
#include <Orange/Core/Traits.h>
namespace orange
{
enum class BasicErrorCode : int32_t
{
Invalid = -1,
Failed = -2,
Success = 0,
};
template <typename T, typename ErrorCode = BasicErrorCode>
class Result
{
public:
~Result() { Destroy(); }
T* Get()
{
Assert(IsSuccess());
if (!IsSuccess())
return nullptr;
return &RefUnsafe();
}
const T* Get() const
{
Assert(IsSuccess());
if (!IsSuccess())
return nullptr;
return &RefUnsafe();
}
bool IsSuccess() const { return static_cast<int32_t>(m_error) >= 0; }
operator bool() const { return IsSuccess(); }
T* operator ->() { return Get(); }
const T* operator ->() const { return Get(); }
T& operator *() { return *Get(); }
const T& operator *() const { return *Get(); }
protected:
Result() = default;
template <typename... Args>
T& Create(Args&&... args)
{
Assert(!m_created);
m_created = true;
new(&m_data) T(Forward<Args>(args)...);
return RefUnsafe();
}
void Destroy()
{
if (m_created)
{
RefUnsafe().~T();
m_created = false;
}
}
Result& Error(ErrorCode code) { m_error = code; return *this; }
Result& Success() { m_error = ErrorCode::Success; return *this; }
T& RefUnsafe() { return *reinterpret_cast< T*>(&m_data); }
const T& RefUnsafe() const { return *reinterpret_cast<const T*>(&m_data); }
friend T;
AlignedStorage<sizeof(T), alignof(T)> m_data;
ErrorCode m_error = ErrorCode::Invalid;
bool m_created = false;
};
}