Skip to content
sarah edited this page Jan 31, 2022 · 7 revisions
#include <veg/option.hpp>
namespace veg {
template <typename T>
struct Option { /*...*/ };

template <typename T>
auto some(T) -> Option<T>;

inline constexpr struct None {} none;
} // namespace veg

Option<T> is a type that may or may not hold a T.

Interface

Constructors

Default/None constructor

Option<T>::Option(None /* none */) noexcept;
Option<T>::Option() noexcept;

Initializes *this in a valueless state.

Example:

#include <veg/option.hpp>

auto main() -> int {
  using namespace veg;
  Option<int> o{none};
  VEG_ASSERT(o.is_none());
}

Some constructor

Option<T>::Option(Some /* some */, T value) noexcept;

template <typename Fn>
Option<T>::Option(InPlace<Some> /* inplace[some] */, Fn fn) noexcept(nothrow_fn_once<Fn, T>);

Initializes *this with the given value, or by invoking the given function object.

Example:

#include <veg/option.hpp>

auto main() -> int {
  using namespace veg;
  Option<int> o{some, 3};
  VEG_ASSERT(o.is_some());
  VEG_ASSERT(o.contains(ref(3)));
}

Copy constructor

explicit Option<T>::Option(Option const&) noexcept(nothrow_copyable<T>);

Copies the inner value from the source if it's available. Otherwise, initializes *this with none.


Move constructor

Option<T>::Option(Option&&) noexcept(nothrow_movable<T>);

Moves the inner value from the source if it's available. Otherwise, initializes *this with none.


Assignment

Copy assignment

auto Option<T>::operator=(Option const&) noexcept(nothrow_copyable<T> && nothrow_copy_assignable<T>) -> Option const&;

Copies the inner value from the source if it's available. Otherwise, sets *this with none.


Move assignment

auto Option<T>::operator=(Option&&) noexcept(nothrow_movable<T> && nothrow_move_assignable<T>) -> Option const&;

Moves the inner value from the source if it's available. Otherwise, sets *this with none.


Optional interface

Contains

auto Option<T>::is_some() const noexcept -> bool;
auto Option<T>::is_none() const noexcept -> bool;

template <typename U>
auto Option<T>::contains() const noexcept(nothrow_eq<T, U>) -> bool
requires (eq<T, U>);

is_some returns true if the optional holds a value.
is_none returns true if the optional doesn't hold a value.
contains returns true if the optional holds a value and it compares equal to the given value.

Example:

#include <veg/option.hpp>

auto main() -> int {
  using namespace veg;
  auto n = Option<int>{none};
  VEG_ASSERT(n.is_none());

  auto o = some(3);
  VEG_ASSERT(o.is_some());
  VEG_ASSERT(o.contains(ref(3)));
}

Unwrap

auto Option<T>::unwrap() && noexcept(nothrow_movable<T>) -> T;
auto Option<T>::unwrap_unchecked(Unsafe /* unsafe */) && noexcept(nothrow_movable<T>) -> T;

Returns the inner value, unwrap panics if *this doesn't hold a value, while unwrap_unchecked results in undefined behavior in that case.

Example:

#include <veg/option.hpp>

auto main() -> int {
  using namespace veg;
  VEG_ASSERT(some(3).unwrap() == 3);
  VEG_ASSERT(some(3).unwrap_unchecked(unsafe) == 3);
}

Take

auto Option<T>::take() noexcept(nothrow_movable<T>) -> Option<T>;

Returns the inner value if it exists. Otherwise, returns none.
Leaves *this in a none state.

Example:

#include <veg/option.hpp>

auto main() -> int {
  using namespace veg;
  Option<int> a = some(3);
  VEG_ASSERT(a.take() == some(3));
  VEG_ASSERT(a.is_none());

  Option<int> b = none;
  VEG_ASSERT(b.take().is_none());
  VEG_ASSERT(b.is_none());
}

Reset

void Option<T>::reset() noexcept(nothrow_destructible<T>);

Destroys the inner value if it exists, leaving *this in a none state.

Example:

#include <veg/option.hpp>

auto main() -> int {
  using namespace veg;
  Option<int> a = some(3);
  VEG_ASSERT(a.is_some());
  a.reset();
  VEG_ASSERT(a.is_none());
}

Emplace

template <typename Fn>
auto Option<T>::emplace_with(Fn fn) noexcept(nothrow_destructible<T> && nothrow_fn_once<Fn, T>) -> T&
requires (fn_once<Fn, T>);
auto Option<T>::emplace(T value) noexcept(nothrow_movable<T>) -> T&;

emplace_with destroys the current value if it exists and sets *this to the result of the function.
emplace destroys the current value if it exists and sets *this to the given value.

Example:

#include <veg/option.hpp>

auto main() -> int {
  using namespace veg;
  Option<int> a = none;
  VEG_ASSERT(a.is_none());
  a.emplace(3);
  VEG_ASSERT(a.is_some());
  VEG_ASSERT(a.contains(ref(3)));

  a.emplace_with([&](){ return 4; });
  VEG_ASSERT(a.is_some());
  VEG_ASSERT(a.contains(ref(4)));
}

As ref/mut

auto Option<T>::as_ref() const noexcept -> Option<Ref<T>>;
auto Option<T>::as_mut() const noexcept -> Option<RefMut<T>>;

Returns a [mutable] reference to the inner value if it exists. Otherwise, returns none.


Functional interface

Filter

template <typename Fn>
auto Option<T>::filter(Fn fn) && noexcept(nothrow_movable<T> && nothrow_fn_once<Fn, bool, Ref<T>>) -> Option<T>
requires (fn_once<Fn, bool, Ref<T>>);

Returns the inner value if it exists and satisfies the predicate. Otherwise, returns none.


Map

template <typename Fn>
auto Option<T>::map(Fn fn) && noexcept(nothrow_fn_once<Fn, Ret, T>) -> Option<Ret>
requires (fn_once<Fn, Ret, T>);

where Ret is meta::invoke_result_t<Fn, T>.

Returns the result of the stored value when passed to the function, if a value exists. Otherwise, returns none.


Map or

template <typename Fn>
auto Option<T>::map_or(Fn fn, Ret d) && noexcept(nothrow_movable<Ret> && nothrow_fn_once<Fn, Ret, T>) -> Ret
requires (fn_once<Fn, Ret, T>);

where Ret is meta::invoke_result_t<Fn, T>.

Returns the result of the stored value when passed to the function, if a value exists. Otherwise, returns the second parameter.

Map or else

template <typename Fn, typename D>
auto Option<T>::map_or(Fn fn, D d) && noexcept(nothrow_fn_once<Fn, Ret, T> && nothrow_fn_once<D, Ret>) -> Ret
requires (fn_once<Fn, Ret, T> && fn_once<D, Ret>);

where Ret is meta::invoke_result_t<Fn, T>.
Returns the result of the stored value when passed to the function, if a value exists. Otherwise, returns the result of second parameter.

Traits

Implements the fmt::Debug<Option<T>> trait: prints the contained value.
Implements the cmp::Ord<Option<T>, Option<U>> trait and operator==: compares the contained value. An empty Option compares less than a non-empty Option.