82 lines
2.1 KiB
C++
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;
|
|
};
|
|
} |