/* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #include #include namespace gfxstream { template class unexpected; template unexpected(E) -> unexpected; #define ENABLE_IF(...) typename std::enable_if<__VA_ARGS__>::type* = nullptr template class expected { public: constexpr expected() = default; constexpr expected(const expected& rhs) = default; constexpr expected(expected&& rhs) = default; template ::value)> constexpr expected(T&& v) : mVariant(std::in_place_index<0>, std::forward(v)) {} template::value)> constexpr expected(std::in_place_t, Args&&... args) : mVariant(std::in_place_index<0>, std::forward(args)...) {} constexpr expected(const unexpected& u) : mVariant(std::in_place_index<1>, u.value()) {} template::value)> constexpr expected(const unexpected& e) : mVariant(std::in_place_index<1>, e.value()) {} constexpr const T* operator->() const { return std::addressof(value()); } constexpr T* operator->() { return std::addressof(value()); } constexpr const T& operator*() const& { return value(); } constexpr T& operator*() & { return value(); } constexpr const T&& operator*() const&& { return std::move(std::get(mVariant)); } constexpr T&& operator*() && { return std::move(std::get(mVariant)); } constexpr bool has_value() const { return mVariant.index() == 0; } constexpr bool ok() const { return has_value(); } template ::value)> constexpr const T& value() const& { return std::get(mVariant); } template ::value)> constexpr T& value() & { return std::get(mVariant); } constexpr const T&& value() const&& { return std::move(std::get(mVariant)); } constexpr T&& value() && { return std::move(std::get(mVariant)); } constexpr const E& error() const& { return std::get(mVariant); } constexpr E& error() & { return std::get(mVariant); } constexpr const E&& error() const&& { return std::move(std::get(mVariant)); } constexpr E&& error() && { return std::move(std::get(mVariant)); } template >> constexpr expected transform_error(F&& function) { if (ok()) { if constexpr (std::is_void_v) { return expected(); } else { return expected(std::in_place, value()); } } else { return unexpected(std::invoke(std::forward(function), error())); } } private: std::variant mVariant; }; template class unexpected { public: constexpr unexpected(const unexpected&) = default; template constexpr explicit unexpected(T&& e) : mError(std::forward(e)) {} template::value)> constexpr explicit unexpected(std::in_place_t, Args&&... args) : mError(std::forward(args)...) {} constexpr const E& value() const& noexcept { return mError; } constexpr E& value() & noexcept { return mError; } constexpr const E&& value() const&& noexcept { return std::move(mError); } constexpr E&& value() && noexcept { return std::move(mError); } private: E mError; }; #define GFXSTREAM_EXPECT(x) \ ({ \ auto local_expected = (x); \ if (!local_expected.ok()) { \ return gfxstream::unexpected(local_expected.error()); \ }; \ std::move(local_expected.value()); \ }) class Ok {}; } // namespace gfxstream