]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/boost/boost/leaf/result.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / leaf / result.hpp
diff --git a/ceph/src/boost/boost/leaf/result.hpp b/ceph/src/boost/boost/leaf/result.hpp
new file mode 100644 (file)
index 0000000..adc7546
--- /dev/null
@@ -0,0 +1,480 @@
+#ifndef BOOST_LEAF_RESULT_HPP_INCLUDED
+#define BOOST_LEAF_RESULT_HPP_INCLUDED
+
+// Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc.
+
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_LEAF_ENABLE_WARNINGS
+#   if defined(__clang__)
+#       pragma clang system_header
+#   elif (__GNUC__*100+__GNUC_MINOR__>301)
+#       pragma GCC system_header
+#   elif defined(_MSC_VER)
+#       pragma warning(push,1)
+#   endif
+#endif
+
+#include <boost/leaf/error.hpp>
+#include <climits>
+
+namespace boost { namespace leaf {
+
+    class bad_result:
+        public std::exception,
+        public error_id
+    {
+        char const * what() const noexcept final override
+        {
+            return "boost::leaf::bad_result";
+        }
+
+    public:
+
+        explicit bad_result( error_id id ) noexcept:
+            error_id(id)
+        {
+            BOOST_LEAF_ASSERT(value());
+        }
+    };
+
+    ////////////////////////////////////////
+
+    namespace leaf_detail
+    {
+        template <class T>
+        struct stored
+        {
+            using type = T;
+            using value_type = T;
+            using value_type_const = T const;
+            using value_cref = T const &;
+            using value_ref = T &;
+            using value_rv_cref = T const &&;
+            using value_rv_ref = T &&;
+        };
+
+        template <class T>
+        struct stored<T &>
+        {
+            using type = std::reference_wrapper<T>;
+            using value_type_const = T;
+            using value_type = T;
+            using value_ref = T &;
+            using value_cref = T &;
+            using value_rv_ref = T &;
+            using value_rv_cref = T &;
+        };
+
+        class result_discriminant
+        {
+            unsigned state_;
+
+        public:
+
+            enum kind_t
+            {
+                no_error = 0,
+                err_id = 1,
+                ctx_ptr = 2,
+                val = 3
+            };
+
+            explicit result_discriminant( error_id id ) noexcept:
+                state_(id.value())
+            {
+                BOOST_LEAF_ASSERT(state_==0 || (state_&3)==1);
+            }
+
+            struct kind_val { };
+            explicit result_discriminant( kind_val ) noexcept:
+                state_(val)
+            {
+            }
+
+            struct kind_ctx_ptr { };
+            explicit result_discriminant( kind_ctx_ptr ) noexcept:
+                state_(ctx_ptr)
+            {
+            }
+
+            kind_t kind() const noexcept
+            {
+                return kind_t(state_&3);
+            }
+
+            error_id get_error_id() const noexcept
+            {
+                BOOST_LEAF_ASSERT(kind()==no_error || kind()==err_id);
+                return make_error_id(state_);
+            }
+        };
+    }
+
+    ////////////////////////////////////////
+
+    template <class T>
+    class result
+    {
+        template <class U>
+        friend class result;
+
+        using result_discriminant = leaf_detail::result_discriminant;
+
+        struct error_result
+        {
+            error_result( error_result && ) = default;
+            error_result( error_result const & ) = delete;
+            error_result & operator=( error_result const & ) = delete;
+
+            result & r_;
+
+            error_result( result & r ) noexcept:
+                r_(r)
+            {
+            }
+
+            template <class U>
+            operator result<U>() noexcept
+            {
+                switch(r_.what_.kind())
+                {
+                case result_discriminant::val:
+                    return result<U>(error_id());
+                case result_discriminant::ctx_ptr:
+                    return result<U>(std::move(r_.ctx_));
+                default:
+                    return result<U>(std::move(r_.what_));
+                }
+            }
+
+            operator error_id() noexcept
+            {
+                switch(r_.what_.kind())
+                {
+                case result_discriminant::val:
+                    return error_id();
+                case result_discriminant::ctx_ptr:
+                {
+                    error_id captured_id = r_.ctx_->propagate_captured_errors();
+                    leaf_detail::id_factory<>::current_id = captured_id.value();
+                    return captured_id;
+                }
+                default:
+                    return r_.what_.get_error_id();
+                }
+            }
+        };
+
+        using stored_type = typename leaf_detail::stored<T>::type;
+        using value_type = typename leaf_detail::stored<T>::value_type;
+        using value_type_const = typename leaf_detail::stored<T>::value_type_const;
+        using value_ref = typename leaf_detail::stored<T>::value_ref;
+        using value_cref = typename leaf_detail::stored<T>::value_cref;
+        using value_rv_ref = typename leaf_detail::stored<T>::value_rv_ref;
+        using value_rv_cref = typename leaf_detail::stored<T>::value_rv_cref;
+
+        union
+        {
+            stored_type stored_;
+            context_ptr ctx_;
+        };
+
+        result_discriminant what_;
+
+        void destroy() const noexcept
+        {
+            switch(this->what_.kind())
+            {
+            case result_discriminant::val:
+                stored_.~stored_type();
+                break;
+            case result_discriminant::ctx_ptr:
+                BOOST_LEAF_ASSERT(!ctx_ || ctx_->captured_id_);
+                ctx_.~context_ptr();
+            default:
+                break;
+            }
+        }
+
+        template <class U>
+        result_discriminant move_from( result<U> && x ) noexcept
+        {
+            auto x_what = x.what_;
+            switch(x_what.kind())
+            {
+            case result_discriminant::val:
+                (void) new(&stored_) stored_type(std::move(x.stored_));
+                break;
+            case result_discriminant::ctx_ptr:
+                BOOST_LEAF_ASSERT(!x.ctx_ || x.ctx_->captured_id_);
+                (void) new(&ctx_) context_ptr(std::move(x.ctx_));
+            default:
+                break;
+            }
+            return x_what;
+        }
+
+        result( result_discriminant && what ) noexcept:
+            what_(std::move(what))
+        {
+            BOOST_LEAF_ASSERT(what_.kind()==result_discriminant::err_id || what_.kind()==result_discriminant::no_error);
+        }
+
+        error_id get_error_id() const noexcept
+        {
+            BOOST_LEAF_ASSERT(what_.kind()!=result_discriminant::val);
+            return what_.kind()==result_discriminant::ctx_ptr ? ctx_->captured_id_ : what_.get_error_id();
+        }
+
+        static int init_T_with_U( T && );
+
+    protected:
+
+        void enforce_value_state() const
+        {
+            if( what_.kind() != result_discriminant::val )
+                ::boost::leaf::throw_exception(bad_result(get_error_id()));
+        }
+
+    public:
+
+        result( result && x ) noexcept:
+            what_(move_from(std::move(x)))
+        {
+        }
+
+        template <class U>
+        result( result<U> && x ) noexcept:
+            what_(move_from(std::move(x)))
+
+        {
+        }
+
+        result():
+            stored_(stored_type()),
+            what_(result_discriminant::kind_val{})
+        {
+        }
+
+        result( value_type && v ) noexcept:
+            stored_(std::forward<value_type>(v)),
+            what_(result_discriminant::kind_val{})
+        {
+        }
+
+        result( value_type const & v ):
+            stored_(v),
+            what_(result_discriminant::kind_val{})
+        {
+        }
+
+        result( error_id err ) noexcept:
+            what_(err)
+        {
+        }
+
+        // SFINAE: T can be initialized with a U, e.g. result<std::string>("literal").
+        // Not using is_constructible on purpose, bug with COMPILER=/usr/bin/clang++ CXXSTD=11 clang 3.3.
+        template <class U>
+        result( U && u, decltype(init_T_with_U(std::forward<U>(u))) * = 0 ):
+            stored_(std::forward<U>(u)),
+            what_(result_discriminant::kind_val{})
+        {
+        }
+
+        result( std::error_code const & ec ) noexcept:
+            what_(error_id(ec))
+        {
+        }
+
+        template <class Enum>
+        result( Enum e, typename std::enable_if<std::is_error_code_enum<Enum>::value, int>::type * = 0 ) noexcept:
+            what_(error_id(e))
+        {
+        }
+
+        result( context_ptr && ctx ) noexcept:
+            ctx_(std::move(ctx)),
+            what_(result_discriminant::kind_ctx_ptr{})
+        {
+        }
+
+        ~result() noexcept
+        {
+            destroy();
+        }
+
+        result & operator=( result && x ) noexcept
+        {
+            destroy();
+            what_ = move_from(std::move(x));
+            return *this;
+        }
+
+        template <class U>
+        result & operator=( result<U> && x ) noexcept
+        {
+            destroy();
+            what_ = move_from(std::move(x));
+            return *this;
+        }
+
+        explicit operator bool() const noexcept
+        {
+            return what_.kind() == result_discriminant::val;
+        }
+
+        value_cref value() const &
+        {
+            enforce_value_state();
+            return stored_;
+        }
+
+        value_ref value() &
+        {
+            enforce_value_state();
+            return stored_;
+        }
+
+        value_rv_cref value() const &&
+        {
+            enforce_value_state();
+            return std::move(stored_);
+        }
+
+        value_rv_ref value() &&
+        {
+            enforce_value_state();
+            return std::move(stored_);
+        }
+
+        value_cref operator*() const &
+        {
+            return value();
+        }
+
+        value_ref operator*() &
+        {
+            return value();
+        }
+
+        value_rv_cref operator*() const &&
+        {
+            return value();
+        }
+
+        value_rv_ref operator*() &&
+        {
+            return value();
+        }
+
+        value_type_const * operator->() const
+        {
+            return &value();
+        }
+
+        value_type * operator->()
+        {
+            return &value();
+        }
+
+        error_result error() noexcept
+        {
+            return error_result{*this};
+        }
+
+        template <class... Item>
+        error_id load( Item && ... item ) noexcept
+        {
+            return error_id(error()).load(std::forward<Item>(item)...);
+        }
+    };
+
+    ////////////////////////////////////////
+
+    namespace leaf_detail
+    {
+        struct void_ { };
+    }
+
+    template <>
+    class result<void>:
+        result<leaf_detail::void_>
+    {
+        using result_discriminant = leaf_detail::result_discriminant;
+        using void_ = leaf_detail::void_;
+        using base = result<void_>;
+
+        template <class U>
+        friend class result;
+
+        result( result_discriminant && what ) noexcept:
+            base(std::move(what))
+        {
+        }
+
+    public:
+
+        using value_type = void;
+
+        result( result && x ) noexcept:
+            base(std::move(x))
+        {
+        }
+
+        result() noexcept
+        {
+        }
+
+        result( error_id err ) noexcept:
+            base(err)
+        {
+        }
+
+        result( std::error_code const & ec ) noexcept:
+            base(ec)
+        {
+        }
+
+        template <class Enum>
+        result( Enum e, typename std::enable_if<std::is_error_code_enum<Enum>::value, Enum>::type * = 0 ) noexcept:
+            base(e)
+        {
+        }
+
+        result( context_ptr && ctx ) noexcept:
+            base(std::move(ctx))
+        {
+        }
+
+        ~result() noexcept
+        {
+        }
+
+        void value() const
+        {
+            base::enforce_value_state();
+        }
+
+        using base::operator=;
+        using base::operator bool;
+        using base::get_error_id;
+        using base::error;
+        using base::load;
+    };
+
+    ////////////////////////////////////////
+
+    template <class R>
+    struct is_result_type;
+
+    template <class T>
+    struct is_result_type<result<T>>: std::true_type
+    {
+    };
+
+} }
+
+#endif