#ifndef GI_EXPECTED_HPP #define GI_EXPECTED_HPP #include "base.hpp" #include "exception.hpp" GI_MODULE_EXPORT namespace gi { // alias so we might route to a std type some day ... template #ifdef expected_lite_VERSION using expected = nonstd::expected; #else using expected = std::expected; #endif template #ifdef expected_lite_VERSION using unexpected = nonstd::unexpected_type; #else using unexpected = std::unexpected; #endif // standardize on glib error template using result = expected; namespace detail { // only use nonstd if it does not delegate to std (in incomplete way) #if defined(expected_lite_VERSION) && !nsel_USES_STD_EXPECTED inline unexpected make_unexpected(repository::GLib::Error error) { assert(error); return nonstd::make_unexpected(std::move(error)); } #else inline unexpected make_unexpected(repository::GLib::Error error) { assert(error); return std::unexpected(std::move(error)); } #endif inline unexpected make_unexpected(GError *error) { assert(error); return make_unexpected(repository::GLib::Error(error)); } } // namespace detail // no forwarding reference; T must be non-reference type template result make_result(T t, GError *error) { if (error) return detail::make_unexpected(error); return t; } // rough helpers to unwrap result/expected // unwrap by move template T expect(gi::result &&t) { if (!t) { g_critical("error result %s", t.error().what()); detail::try_throw(std::move(t.error())); } return std::move(*t); } namespace detail { template void test_result(const gi::result &); template int test_result(const T &); template using is_result = std::is_same(std::declval())))>; } // namespace detail // should only be used for a non-result // (e.g. avoid l-value result ending up here) template::value>::type> T expect(T &&t) { return std::forward(t); } template struct rv { #if GI_DL && GI_EXPECTED using type = gi::result; #else using type = T; #endif }; } // namespace gi #endif // GI_EXPECTED_HPP