Skip to content

Instantly share code, notes, and snippets.

@H2CO3
Created October 10, 2023 15:40
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save H2CO3/52613a9a200f742b1aea07fec655df96 to your computer and use it in GitHub Desktop.
Save H2CO3/52613a9a200f742b1aea07fec655df96 to your computer and use it in GitHub Desktop.
Safe, simple Option<T> for C++
#include <iostream>
#include <iomanip>
template<typename T>
union OptionInner {
T full;
char empty;
OptionInner(): empty(0) {}
~OptionInner() {}
};
template<typename T>
struct Option {
private:
OptionInner<T> inner;
bool is_full;
public:
Option():
is_full(false)
{}
Option(T value):
is_full(true)
{
new (&this->inner.full) T(std::move(value));
}
Option(const Option<T> &) = default;
Option(Option<T> &&) = default;
~Option() {
if (this->is_full) {
this->inner.full.~T();
}
}
Option &operator=(Option<T> value) {
this->inner = std::move(value.inner);
this->is_full = value.is_full;
return *this;
}
bool has_value() const {
return this->is_full;
}
const T &operator*() const {
if (!this->is_full) {
throw std::runtime_error("Option was empty");
}
return this->inner.full;
}
T &operator*() {
if (!this->is_full) {
throw std::runtime_error("Option was empty");
}
return this->inner.full;
}
const T *operator->() const {
return &**this;
}
T *operator->() {
return &**this;
}
};
int main() {
const Option<int> empty;
const Option<std::string> full { std::string("I'm a string") };
std::cout << std::boolalpha;
std::cout << "empty has a value: " << empty.has_value() << '\n';
std::cout << "full contains: " << *full << '\n';
// std::cout << "empty contains: " << *empty << '\n'; // throws
return 0;
}
@jendrikw
Copy link

I'm curious: What does char empty; do? Seems unused to me.

@H2CO3
Copy link
Author

H2CO3 commented Oct 11, 2023

It's to have something to initialize the union with when the option is empty.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment