General Purpose library for Freestanding C++ and POSIX systems
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

100 lines
1.5 KiB

#pragma once
#include <type_traits>
#include "gp_config.hpp"
#include "gp/exception.hpp"
#include "gp/memory.hpp"
namespace gp{
struct nullopt_t{};
constexpr nullopt_t nullopt;
template<typename T, bool B = std::is_final<T>::value || std::is_fundamental<T>::value>
class optional;
template<typename T>
class optional<T,true>{
bool ready = false;
char buffer[sizeof(T)];
public:
constexpr optional()
: ready{false}
{}
constexpr optional(nullopt_t)
: ready{false}
{}
constexpr optional(T& value)
: ready{true}
{
new(buffer) T(value);
}
constexpr optional(T&& value)
: ready{true}
{
new(buffer) T(std::move(value));
}
constexpr bool has_value()
{
return ready;
}
constexpr T& value()
{
if constexpr (gp_config::has_exceptions)
{
if(!ready)
{
throw bad_optional{};
}
}
return *reinterpret_cast<T*>(buffer);
}
};
template<typename T>
class optional<T,false>{
bool ready = false;
void* ptr;
public:
constexpr optional()
: ready{false}
{}
constexpr optional(nullopt_t)
: ready{false}
{}
constexpr optional(T& value)
: ready{true}
{
ptr = (void*)new T(value);
}
constexpr optional(T&& value)
: ready{true}
{
ptr = (void*)new T(std::move(value));
}
constexpr bool has_value()
{
return ready;
}
constexpr T& value()
{
if constexpr (gp_config::has_exceptions)
{
if(!ready)
{
throw bad_optional{};
}
}
return *reinterpret_cast<T*>(ptr);
}
};
}