Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-04-19 08:44:21

0001 /*
0002  * Distributed under the Boost Software License, Version 1.0.
0003  * (See accompanying file LICENSE_1_0.txt or copy at
0004  * https://www.boost.org/LICENSE_1_0.txt)
0005  *
0006  * Copyright (c) 2022 Andrey Semashev
0007  */
0008 /*!
0009  * \file scope/scope_success.hpp
0010  *
0011  * This header contains definition of \c scope_success template.
0012  */
0013 
0014 #ifndef BOOST_SCOPE_SCOPE_SUCCESS_HPP_INCLUDED_
0015 #define BOOST_SCOPE_SCOPE_SUCCESS_HPP_INCLUDED_
0016 
0017 #include <type_traits>
0018 #include <boost/scope/detail/config.hpp>
0019 #include <boost/scope/exception_checker.hpp>
0020 #include <boost/scope/scope_exit.hpp>
0021 #include <boost/scope/detail/is_not_like.hpp>
0022 #include <boost/scope/detail/type_traits/conjunction.hpp>
0023 #include <boost/scope/detail/type_traits/is_invocable.hpp>
0024 #include <boost/scope/detail/type_traits/is_nothrow_invocable.hpp>
0025 #include <boost/scope/detail/header.hpp>
0026 
0027 #ifdef BOOST_HAS_PRAGMA_ONCE
0028 #pragma once
0029 #endif
0030 
0031 namespace boost {
0032 namespace scope {
0033 
0034 template< typename Func, typename Cond >
0035 class scope_success;
0036 
0037 namespace detail {
0038 
0039 // Workaround for clang < 5.0 which can't pass scope_success as a template template parameter from within scope_success definition
0040 template< typename T >
0041 using is_not_like_scope_success = detail::is_not_like< T, scope_success >;
0042 
0043 template< typename Func >
0044 class logical_not;
0045 
0046 template< typename T >
0047 using is_not_like_logical_not = detail::is_not_like< T, logical_not >;
0048 
0049 template< typename Func >
0050 class logical_not
0051 {
0052 public:
0053     using result_type = bool;
0054 
0055 private:
0056     Func m_func;
0057 
0058 public:
0059     template<
0060         bool Requires = std::is_default_constructible< Func >::value,
0061         typename = typename std::enable_if< Requires >::type
0062     >
0063     logical_not() noexcept(std::is_nothrow_default_constructible< Func >::value) :
0064         m_func()
0065     {
0066     }
0067 
0068     template<
0069         typename F,
0070         typename = typename std::enable_if< detail::conjunction<
0071             std::is_constructible< Func, F >,
0072             detail::is_not_like_logical_not< F >
0073         >::value >::type
0074     >
0075     explicit logical_not(F&& func) noexcept(std::is_nothrow_constructible< Func, F >::value) :
0076         m_func(static_cast< F&& >(func))
0077     {
0078     }
0079 
0080     result_type operator()() const noexcept(detail::is_nothrow_invocable< Func const& >::value)
0081     {
0082         return !m_func();
0083     }
0084 };
0085 
0086 } // namespace detail
0087 
0088 /*!
0089  * \brief Scope exit guard that invokes a function upon leaving the scope, if
0090  *        a failure condition is not satisfied.
0091  *
0092  * The scope guard wraps two function objects: the scope guard action and
0093  * a failure condition for invoking the action. Both function objects must
0094  * be callable with no arguments and can be one of:
0095  *
0096  * \li A user-defined class with a public `operator()`.
0097  * \li An lvalue reference to such class.
0098  * \li An lvalue reference or pointer to function taking no arguments.
0099  *
0100  * The condition function object `operator()` must return a value
0101  * contextually convertible to \c true, if the failure is detected and the
0102  * action function object is not allowed to be executed, and \c false otherwise.
0103  * Additionally, the failure condition function object `operator()` must not
0104  * throw, as otherwise the action function object may not be called. If not
0105  * specified, the default failure condition checks whether the scope is left
0106  * due to an exception - the action function object will only be called if
0107  * the scope is left normally.
0108  *
0109  * \sa scope_exit
0110  * \sa scope_fail
0111  *
0112  * \tparam Func Scope guard action function object type.
0113  * \tparam Cond Scope guard failure condition function object type.
0114  */
0115 template< typename Func, typename Cond = exception_checker >
0116 class scope_success :
0117     public scope_exit< Func, detail::logical_not< Cond > >
0118 {
0119 //! \cond
0120 private:
0121     using base_type = scope_exit< Func, detail::logical_not< Cond > >;
0122 
0123 //! \endcond
0124 public:
0125     /*!
0126      * \brief Constructs a scope guard with a given callable function object.
0127      *
0128      * **Requires:** \c Func is constructible from \a func. \c Cond is nothrow default-constructible.
0129      *
0130      * **Effects:** Constructs the scope guard as if by calling
0131      *              `scope_success(std::forward< F >(func), Cond(), active)`.
0132      *
0133      * **Throws:** Nothing, unless construction of the function objects throw.
0134      *
0135      * \param func The callable action function object to invoke on destruction.
0136      * \param active Indicates whether the scope guard should be active upon construction.
0137      *
0138      * \post `this->active() == active`
0139      */
0140     template<
0141         typename F
0142         //! \cond
0143         , typename = typename std::enable_if< detail::conjunction<
0144             std::is_constructible< base_type, F, bool >,
0145             detail::is_not_like_scope_success< F >
0146         >::value >::type
0147         //! \endcond
0148     >
0149     explicit scope_success(F&& func, bool active = true)
0150         noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(std::is_nothrow_constructible< base_type, F, bool >::value)) :
0151         base_type(static_cast< F&& >(func), active)
0152     {
0153     }
0154 
0155     /*!
0156      * \brief Constructs a scope guard with a given callable action and failure condition function objects.
0157      *
0158      * **Requires:** \c Func is constructible from \a func. \c Cond is constructible from \a cond.
0159      *
0160      * **Effects:** If \c Func is nothrow constructible from `F&&` then constructs \c Func from
0161      *              `std::forward< F >(func)`, otherwise constructs from `func`. If \c Cond is
0162      *              nothrow constructible from `C&&` then constructs \c Cond from
0163      *              `std::forward< C >(cond)`, otherwise constructs from `cond`.
0164      *
0165      *              If \c Func or \c Cond construction throws and \a active is \c true, invokes
0166      *              \a cond and, if it returns \c true, \a func before returning with the exception.
0167      *
0168      * **Throws:** Nothing, unless construction of the function objects throw.
0169      *
0170      * \param func The callable action function object to invoke on destruction.
0171      * \param cond The callable failure condition function object.
0172      * \param active Indicates whether the scope guard should be active upon construction.
0173      *
0174      * \post `this->active() == active`
0175      */
0176     template<
0177         typename F,
0178         typename C
0179         //! \cond
0180         , typename = typename std::enable_if< std::is_constructible< base_type, F, C, bool >::value >::type
0181         //! \endcond
0182     >
0183     explicit scope_success(F&& func, C&& cond, bool active = true)
0184         noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(std::is_nothrow_constructible< base_type, F, C, bool >::value)) :
0185         base_type(static_cast< F&& >(func), static_cast< C&& >(cond), active)
0186     {
0187     }
0188 
0189     /*!
0190      * \brief Move-constructs a scope guard.
0191      *
0192      * **Requires:** \c Func and \c Cond are nothrow move-constructible or copy-constructible.
0193      *
0194      * **Effects:** If \c Func is nothrow move-constructible then move-constructs \c Func from
0195      *              a member of \a that, otherwise copy-constructs \c Func. If \c Cond is nothrow
0196      *              move-constructible then move-constructs \c Cond from a member of \a that,
0197      *              otherwise copy-constructs \c Cond.
0198      *
0199      *              If \c Func or \c Cond construction throws and `that.active() == true`, invokes
0200      *              \c Cond object stored in \a that and, if it returns \c true, \a Func object
0201      *              (either the newly constructed one, if its construction succeeded, or the original
0202      *              one stored in \a that) before returning with the exception.
0203      *
0204      *              If the construction succeeds, marks \a that as inactive.
0205      *
0206      * **Throws:** Nothing, unless move-construction of the function objects throw.
0207      *
0208      * \param that Move source.
0209      *
0210      * \post `that.active() == false`
0211      */
0212     //! \cond
0213     template<
0214         bool Requires = std::is_move_constructible< base_type >::value,
0215         typename = typename std::enable_if< Requires >::type
0216     >
0217     //! \endcond
0218     scope_success(scope_success&& that)
0219         noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(std::is_nothrow_move_constructible< base_type >::value)) :
0220         base_type(static_cast< base_type&& >(that))
0221     {
0222     }
0223 
0224     scope_success& operator= (scope_success&&) = delete;
0225 
0226     scope_success(scope_success const&) = delete;
0227     scope_success& operator= (scope_success const&) = delete;
0228 };
0229 
0230 #if !defined(BOOST_NO_CXX17_DEDUCTION_GUIDES)
0231 template< typename Func >
0232 explicit scope_success(Func) -> scope_success< Func >;
0233 
0234 template< typename Func >
0235 explicit scope_success(Func, bool) -> scope_success< Func >;
0236 
0237 template<
0238     typename Func,
0239     typename Cond,
0240     typename = typename std::enable_if< detail::is_invocable< Cond const& >::value >::type
0241 >
0242 explicit scope_success(Func, Cond) -> scope_success< Func, Cond >;
0243 
0244 template<
0245     typename Func,
0246     typename Cond,
0247     typename = typename std::enable_if< detail::is_invocable< Cond const& >::value >::type
0248 >
0249 explicit scope_success(Func, Cond, bool) -> scope_success< Func, Cond >;
0250 #endif // !defined(BOOST_NO_CXX17_DEDUCTION_GUIDES)
0251 
0252 /*!
0253  * \brief Creates a scope fail guard with a given action function object.
0254  *
0255  * **Effects:** Constructs a scope guard as if by calling
0256  *              `scope_success< std::decay_t< F > >(std::forward< F >(func), active)`.
0257  *
0258  * \param func The callable function object to invoke on destruction.
0259  * \param active Indicates whether the scope guard should be active upon construction.
0260  */
0261 template< typename F >
0262 inline scope_success< typename std::decay< F >::type > make_scope_success(F&& func, bool active = true)
0263     noexcept(std::is_nothrow_constructible<
0264         scope_success< typename std::decay< F >::type >,
0265         F,
0266         bool
0267     >::value)
0268 {
0269     return scope_success< typename std::decay< F >::type >(static_cast< F&& >(func), active);
0270 }
0271 
0272 /*!
0273  * \brief Creates a scope fail with given callable function objects.
0274  *
0275  * **Effects:** Constructs a scope guard as if by calling
0276  *              `scope_success< std::decay_t< F >, std::decay_t< C > >(
0277  *              std::forward< F >(func), std::forward< C >(cond), active)`.
0278  *
0279  * \param func The callable action function object to invoke on destruction.
0280  * \param cond The callable failure condition function object.
0281  * \param active Indicates whether the scope guard should be active upon construction.
0282  */
0283 template< typename F, typename C >
0284 inline
0285 #if !defined(BOOST_SCOPE_DOXYGEN)
0286 typename std::enable_if<
0287     detail::is_invocable< C const& >::value,
0288     scope_success< typename std::decay< F >::type, typename std::decay< C >::type >
0289 >::type
0290 #else
0291 scope_success< typename std::decay< F >::type, typename std::decay< C >::type >
0292 #endif
0293 make_scope_success(F&& func, C&& cond, bool active = true)
0294     noexcept(std::is_nothrow_constructible<
0295         scope_success< typename std::decay< F >::type, typename std::decay< C >::type >,
0296         F,
0297         C,
0298         bool
0299     >::value)
0300 {
0301     return scope_success< typename std::decay< F >::type, typename std::decay< C >::type >(static_cast< F&& >(func), static_cast< C&& >(cond), active);
0302 }
0303 
0304 } // namespace scope
0305 } // namespace boost
0306 
0307 #include <boost/scope/detail/footer.hpp>
0308 
0309 #endif // BOOST_SCOPE_SCOPE_SUCCESS_HPP_INCLUDED_