/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * 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 /// `result` <-> `Try` conversions to aid in migrating legacy `Try` code. /// /// Perfect interconversion is not always possible: /// - `Try` does not support reference types, but `result` does. /// - `Try` has 3 states. Value & error interconvert transparently. For the /// empty state, `try_to_result` has a 2nd arg to set the policy. #if FOLLY_HAS_RESULT namespace folly { // NB: If `T` is a reference type, this will fail with a `Try` static assert. template Try result_to_try(result r) noexcept( std::is_nothrow_move_constructible_v) { if (r.has_value()) { if constexpr (std::is_void_v) { return Try{}; } else { return Try{std::move(r).value_or_throw()}; } } else { return Try{std::move(r).non_value().get_legacy_error_or_cancellation()}; } } inline constexpr struct empty_try_as_error_t { template result on_empty_try() const { return {non_value_result{UsingUninitializedTry{}}}; } } empty_try_as_error; template class empty_try_with { private: Fn fn_; public: explicit empty_try_with(Fn fn) : fn_(std::move(fn)) {} template result on_empty_try() && { return {std::move(fn_)()}; } }; /// If `t` is empty, defaults to returning a `UsingUninitializedTry` result. /// Pick your own default via `empty_try_with{[]() { return result{...}; }`. template result try_to_result(Try t, IfEmpty if_empty) noexcept( std::is_nothrow_move_constructible_v && noexcept(std::move(if_empty).template on_empty_try())) { if (t.hasValue()) { if constexpr (std::is_void_v) { return result{}; } else { return {std::move(t).value()}; } } else if (t.hasException()) { return {non_value_result::make_legacy_error_or_cancellation( std::move(t).exception())}; } else { return std::move(if_empty).template on_empty_try(); } } template result try_to_result(Try t) noexcept( std::is_nothrow_move_constructible_v) { return try_to_result(std::move(t), empty_try_as_error); } } // namespace folly #endif // FOLLY_HAS_RESULT