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