Skip to content

Instantly share code, notes, and snippets.

@cdhowie
Created May 14, 2020 16:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cdhowie/4985d7a461e1cf61ee0cfb29cf9e3dc2 to your computer and use it in GitHub Desktop.
Save cdhowie/4985d7a461e1cf61ee0cfb29cf9e3dc2 to your computer and use it in GitHub Desktop.
#ifndef OPTIONAL_HPP
#define OPTIONAL_HPP
#include <utility>
namespace gamesolver {
template <typename T>
class optional {
public:
optional() noexcept;
~optional();
optional(T const &);
optional(T &&);
optional(optional const &);
optional(optional &&);
optional & operator=(T const &);
optional & operator=(T &&);
optional & operator=(optional const &);
optional & operator=(optional &&);
void swap(optional &) noexcept;
bool has_value() const noexcept;
explicit operator bool() const noexcept;
T & operator*() noexcept;
T const & operator*() const noexcept;
T * get() noexcept;
T const * get() const noexcept;
T * operator->() noexcept;
T const * operator->() const noexcept;
void clear();
template <typename... Args>
void emplace(Args && ...);
private:
char mem[sizeof(T)];
T * target;
};
template <typename T>
optional<T>::optional() noexcept : target{nullptr} { }
template <typename T>
optional<T>::~optional() {
clear();
}
template <typename T>
optional<T>::optional(optional const & other) : optional{} {
*this = other;
}
template <typename T>
optional<T>::optional(optional && other) : optional{} {
*this = std::move(other);
}
template <typename T>
optional<T>::optional(T const & other) :
target{new (mem) T{other}} { }
template <typename T>
optional<T>::optional(T && other) :
target{new (mem) T{std::move(other)}} { }
template <typename T>
optional<T> & optional<T>::operator=(optional const & other) {
if (!other.has_value()) {
clear();
} else if (has_value()) {
*target = *other;
} else {
target = new (mem) T{*other};
}
return *this;
}
template <typename T>
optional<T> & optional<T>::operator=(optional && other) {
if (!other.has_value()) {
clear();
} else if (has_value()) {
*target = std::move(*other);
other.clear();
} else {
target = new (mem) T{std::move(*other)};
other.clear();
}
return *this;
}
template <typename T>
optional<T> & optional<T>::operator=(T const & other) {
if (has_value()) {
*target = other;
} else {
target = new (mem) T{other};
}
return *this;
}
template <typename T>
optional<T> & optional<T>::operator=(T && other) {
if (has_value()) {
*target = std::move(other);
} else {
target = new (mem) T{std::move(other)};
}
return *this;
}
template <typename T>
template <typename... Args>
void optional<T>::emplace(Args && ... args) {
clear();
target = new (mem) T{std::forward<Args>(args)...};
}
template <typename T>
bool optional<T>::has_value() const noexcept {
return target != nullptr;
}
template <typename T>
optional<T>::operator bool() const noexcept {
return has_value();
}
template <typename T>
void optional<T>::swap(optional & other) noexcept {
std::swap(mem, other.mem);
std::swap(target, other.target);
}
template <typename T>
T * optional<T>::get() noexcept {
return target;
}
template <typename T>
T const * optional<T>::get() const noexcept {
return target;
}
template <typename T>
T * optional<T>::operator->() noexcept {
return get();
}
template <typename T>
T const * optional<T>::operator->() const noexcept {
return get();
}
template <typename T>
T & optional<T>::operator*() noexcept {
return *get();
}
template <typename T>
T const & optional<T>::operator*() const noexcept {
return *get();
}
template <typename T>
void optional<T>::clear() {
if (target != nullptr) {
target->~T();
target = nullptr;
}
}
template <typename T>
void swap(optional<T> & a, optional<T> & b) {
a.swap(b);
}
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment