libcruft-util/expected.hpp

109 lines
2.6 KiB
C++
Raw Normal View History

/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Copyright 2019 Danny Robson <danny@nerdcruft.net>
*/
2019-02-07 17:20:35 +11:00
#pragma once
#include <exception>
2019-02-07 17:33:47 +11:00
#include <functional>
///////////////////////////////////////////////////////////////////////////////
namespace cruft {
class bad_expected_access : public std::exception {
public:
char const* what (void) const noexcept override
{
return "bad_expected_access";
}
};
template <typename ValueT, typename ErrorT>
struct expected {
using value_type = ValueT;
using error_type = ErrorT;
expected (ValueT &&_value)
{
::new (&m_store.value) ValueT (std::move (_value));
m_valid = true;
}
expected (ErrorT &&_error)
{
::new (&m_store.error) ErrorT (std::move (_error));
}
~expected ()
{
if (m_valid) {
m_store.value.~ValueT ();
m_valid = false;
} else {
m_store.error.~ErrorT ();
}
}
ValueT&
value (void)&
{
if (!m_valid)
throw bad_expected_access {};
return m_store.value;
}
ValueT&&
value (void)&&
{
if (!m_valid)
throw bad_expected_access {};
return std::move (m_store.value);
}
ErrorT&
error (void)&
{
if (m_valid)
throw bad_expected_access {};
return m_store.error;
}
ErrorT&&
error (void)&&
{
if (m_valid)
throw bad_expected_access {};
return std::move (m_store.error);
}
ValueT* operator-> (void)& { return &value (); }
ValueT& operator* (void)& { return value (); }
2019-02-07 17:33:47 +11:00
template <typename FunctionT, typename ...ArgsT>
expected then (FunctionT &&func, ArgsT &&...args)
{
if (!m_valid)
return *this;
else
return expected (std::invoke (func, args..., value ()));
}
explicit operator bool() const noexcept { return m_valid; }
private:
union storage_t {
storage_t () {};
~storage_t () {};
char defer;
ValueT value;
ErrorT error;
} m_store;
bool m_valid = false;
};
};