Skip to content

Instantly share code, notes, and snippets.

@hqhs
Created December 8, 2019 14:18
Show Gist options
  • Save hqhs/c5532f773e957f8717c4c06030f4f3c8 to your computer and use it in GitHub Desktop.
Save hqhs/c5532f773e957f8717c4c06030f4f3c8 to your computer and use it in GitHub Desktop.
Updated "expected" version from Andrei Alexandrescu
template <class T, class E> class expected
{
union {
T yay;
E nay;
};
bool ok = true;
public:
expected() { new (&yay) T(); }
expected(const T &rhs) { new (&yay) T(rhs); }
expected(const unexpected<E> &rhs) : ok(false) { new (&nay) E(rhs.value()); }
template <class U = T> explicit expected(U &&rhs)
{
new (&yay) T(forward<U>(rhs));
}
expected(const expected &rhs) : ok(rhs.ok)
{
if (ok)
new (&yay) T(rhs.yay);
else
new (&nay) E(rhs.nay);
}
expected(expected &&rhs) : ok(rhs.ok)
{
if (ok)
new (&yay) T(std::move(rhs.yay));
else
new (&nay) E(std::move(rhs.nay));
}
T &operator*()
{
// if (!ok) throw nay;
return yay; // UB galore
}
const T &operator*() const;
T &&operator*() &&;
const T &&operator*() const &&;
T *operator->() { return &**this; }
const T *operator->() const;
const E &error() const
{
assert(!ok);
return nay;
}
E &error();
E &&error() &&;
const E &&error() const &&;
bool has_value() const noexcept { return ok; }
explicit operator bool() const noexcept { return ok; }
T &expected::value() &
{
if (!ok)
throw nay;
return yay;
}
const T &expected::value() const &;
T &&expected::value() &&;
const T &&expected::value() const &&; // any useful scenario?
// Returns value() of ok, T(forward<U>(v)) otherwise
template <class U> T value_or(U &&v) const &;
template <class U> T value_or(U &&v) &&;
enable_if_t<is_nothrow_move_constructible_v<T> && is_swappable_v<T &> &&
is_nothrow_move_constructible_v<E> && is_swappable_v<E &>>
swap(expected &rhs)
{
if (ok)
{
if (rhs.ok)
{
using std::swap;
swap(yay, rhs.yay);
}
else
{
rhs.swap(*this);
}
}
else
{
if (!rhs.ok)
{
using std::swap;
swap(nay, rhs.nay);
}
else
{
E t{std::move(nay)};
nay.~E();
new (&yay) T(std::move(rhs.yay));
ok = true;
rhs.yay.~T();
new (&rhs.nay) E(std::move(t));
rhs.ok = false;
}
}
}
}
@hqhs
Copy link
Author

hqhs commented Dec 8, 2019

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