This commit is contained in:
2026-03-23 20:54:41 +08:00
commit e13b3650e9
4596 changed files with 1015768 additions and 0 deletions

View File

@@ -0,0 +1,180 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* https://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2022-2024 Andrey Semashev
*/
/*!
* \file scope/defer.hpp
*
* This header contains definition of \c defer_guard template.
*/
#ifndef BOOST_SCOPE_DEFER_HPP_INCLUDED_
#define BOOST_SCOPE_DEFER_HPP_INCLUDED_
#include <type_traits>
#include <boost/scope/detail/config.hpp>
#include <boost/scope/detail/is_not_like.hpp>
#include <boost/scope/detail/move_or_copy_construct_ref.hpp>
#include <boost/scope/detail/type_traits/conjunction.hpp>
#include <boost/scope/detail/type_traits/is_nothrow_invocable.hpp>
#include <boost/scope/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace scope {
template< typename Func >
class defer_guard;
namespace detail {
// Workaround for clang < 5.0 which can't pass defer_guard as a template template parameter from within defer_guard definition
template< typename T >
using is_not_like_defer_guard = detail::is_not_like< T, defer_guard >;
} // namespace detail
/*!
* \brief Defer guard that invokes a function upon leaving the scope.
*
* The scope guard wraps a function object callable with no arguments
* that can be one of:
*
* \li A user-defined class with a public `operator()`.
* \li An lvalue reference to such class.
* \li An lvalue reference or pointer to function taking no arguments.
*
* The defer guard unconditionally invokes the wrapped function object
* on destruction.
*/
template< typename Func >
class defer_guard
{
//! \cond
private:
struct data
{
Func m_func;
template< typename F, typename = typename std::enable_if< std::is_constructible< Func, F >::value >::type >
explicit data(F&& func, std::true_type) noexcept :
m_func(static_cast< F&& >(func))
{
}
template< typename F, typename = typename std::enable_if< std::is_constructible< Func, F >::value >::type >
explicit data(F&& func, std::false_type) try :
m_func(static_cast< F&& >(func))
{
}
catch (...)
{
func();
}
};
data m_data;
//! \endcond
public:
/*!
* \brief Constructs a defer guard with a given callable function object.
*
* **Requires:** \c Func is constructible from \a func.
*
* **Effects:** If \c Func is nothrow constructible from `F&&` then constructs \c Func from
* `std::forward< F >(func)`, otherwise constructs from `func`.
*
* If \c Func construction throws, invokes \a func before returning with the exception.
*
* **Throws:** Nothing, unless construction of the function object throws.
*
* \param func The callable function object to invoke on destruction.
*/
template<
typename F
//! \cond
, typename = typename std::enable_if< detail::conjunction<
std::is_constructible<
data,
typename detail::move_or_copy_construct_ref< F, Func >::type,
typename std::is_nothrow_constructible< Func, typename detail::move_or_copy_construct_ref< F, Func >::type >::type
>,
detail::is_not_like_defer_guard< F >
>::value >::type
//! \endcond
>
defer_guard(F&& func)
noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(
std::is_nothrow_constructible<
data,
typename detail::move_or_copy_construct_ref< F, Func >::type,
typename std::is_nothrow_constructible< Func, typename detail::move_or_copy_construct_ref< F, Func >::type >::type
>::value
)) :
m_data
(
static_cast< typename detail::move_or_copy_construct_ref< F, Func >::type >(func),
typename std::is_nothrow_constructible< Func, typename detail::move_or_copy_construct_ref< F, Func >::type >::type()
)
{
}
defer_guard(defer_guard const&) = delete;
defer_guard& operator= (defer_guard const&) = delete;
/*!
* \brief Invokes the wrapped callable function object and destroys the callable.
*
* **Throws:** Nothing, unless invoking the callable throws.
*/
~defer_guard() noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(detail::is_nothrow_invocable< Func& >::value))
{
m_data.m_func();
}
};
#if !defined(BOOST_NO_CXX17_DEDUCTION_GUIDES)
template< typename Func >
defer_guard(Func) -> defer_guard< Func >;
#endif // !defined(BOOST_NO_CXX17_DEDUCTION_GUIDES)
} // namespace scope
//! \cond
#if defined(BOOST_MSVC)
#define BOOST_SCOPE_DETAIL_UNIQUE_VAR_TAG __COUNTER__
#else
#define BOOST_SCOPE_DETAIL_UNIQUE_VAR_TAG __LINE__
#endif
//! \endcond
/*!
* \brief The macro creates a uniquely named defer guard.
*
* The macro should be followed by a function object that should be called
* on leaving the current scope. Usage example:
*
* ```
* BOOST_SCOPE_DEFER []
* {
* std::cout << "Hello world!" << std::endl;
* };
* ```
*
* \note Using this macro requires C++17.
*/
#define BOOST_SCOPE_DEFER \
boost::scope::defer_guard BOOST_JOIN(_boost_defer_guard_, BOOST_SCOPE_DETAIL_UNIQUE_VAR_TAG) =
} // namespace boost
#include <boost/scope/detail/footer.hpp>
#endif // BOOST_SCOPE_DEFER_HPP_INCLUDED_

View File

@@ -0,0 +1,102 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* https://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2022 Andrey Semashev
*/
/*!
* \file scope/detail/compact_storage.hpp
*
* This header contains utility helpers for implementing compact storage
* for class members. In particular, it allows to leverage empty base optimization (EBO).
*/
#ifndef BOOST_SCOPE_DETAIL_COMPACT_STORAGE_HPP_INCLUDED_
#define BOOST_SCOPE_DETAIL_COMPACT_STORAGE_HPP_INCLUDED_
#include <type_traits>
#include <boost/scope/detail/config.hpp>
#include <boost/scope/detail/type_traits/is_final.hpp>
#include <boost/scope/detail/type_traits/negation.hpp>
#include <boost/scope/detail/type_traits/conjunction.hpp>
#include <boost/scope/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace scope {
namespace detail {
//! The class allows to place data members in the tail padding of type \a T if the user's class derives from it
template<
typename T,
typename Tag = void,
bool = detail::conjunction< std::is_class< T >, detail::negation< detail::is_final< T > > >::value
>
class compact_storage :
private T
{
public:
template< typename... Args >
constexpr compact_storage(Args&&... args) noexcept(std::is_nothrow_constructible< T, Args... >::value) :
T(static_cast< Args&& >(args)...)
{
}
compact_storage(compact_storage&&) = default;
compact_storage& operator= (compact_storage&&) = default;
compact_storage(compact_storage const&) = default;
compact_storage& operator= (compact_storage const&) = default;
T& get() noexcept
{
return *static_cast< T* >(this);
}
T const& get() const noexcept
{
return *static_cast< const T* >(this);
}
};
template< typename T, typename Tag >
class compact_storage< T, Tag, false >
{
private:
T m_data;
public:
template< typename... Args >
constexpr compact_storage(Args&&... args) noexcept(std::is_nothrow_constructible< T, Args... >::value) :
m_data(static_cast< Args&& >(args)...)
{
}
compact_storage(compact_storage&&) = default;
compact_storage& operator= (compact_storage&&) = default;
compact_storage(compact_storage const&) = default;
compact_storage& operator= (compact_storage const&) = default;
T& get() noexcept
{
return m_data;
}
T const& get() const noexcept
{
return m_data;
}
};
} // namespace detail
} // namespace scope
} // namespace boost
#include <boost/scope/detail/footer.hpp>
#endif // BOOST_SCOPE_DETAIL_COMPACT_STORAGE_HPP_INCLUDED_

View File

@@ -0,0 +1,50 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* https://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2023 Andrey Semashev
*/
/*!
* \file scope/detail/config.hpp
*
* This header contains Boost.Scope common configuration.
*/
#ifndef BOOST_SCOPE_DETAIL_CONFIG_HPP_INCLUDED_
#define BOOST_SCOPE_DETAIL_CONFIG_HPP_INCLUDED_
#include <boost/config.hpp>
#include <boost/scope/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if !(defined(__cpp_noexcept_function_type) && __cpp_noexcept_function_type >= 201510l) && !defined(_NOEXCEPT_TYPES_SUPPORTED)
#define BOOST_SCOPE_NO_CXX17_NOEXCEPT_FUNCTION_TYPES
#endif
#if !defined(BOOST_SCOPE_DETAIL_DOC_ALT)
#if !defined(BOOST_SCOPE_DOXYGEN)
#define BOOST_SCOPE_DETAIL_DOC_ALT(alt, ...) __VA_ARGS__
#else
#define BOOST_SCOPE_DETAIL_DOC_ALT(alt, ...) alt
#endif
#endif
#if !defined(BOOST_SCOPE_DETAIL_DOC_HIDDEN)
#define BOOST_SCOPE_DETAIL_DOC_HIDDEN(...) BOOST_SCOPE_DETAIL_DOC_ALT(..., __VA_ARGS__)
#endif
#if !defined(BOOST_SCOPE_DETAIL_DOC)
#if !defined(BOOST_SCOPE_DOXYGEN)
#define BOOST_SCOPE_DETAIL_DOC(...)
#else
#define BOOST_SCOPE_DETAIL_DOC(...) __VA_ARGS__
#endif
#endif
#include <boost/scope/detail/footer.hpp>
#endif // BOOST_SCOPE_DETAIL_CONFIG_HPP_INCLUDED_

View File

@@ -0,0 +1,22 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* https://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2023 Andrey Semashev
*/
#if !defined(BOOST_SCOPE_ENABLE_WARNINGS)
#if defined(_MSC_VER) && !defined(__clang__)
#pragma warning(pop)
#elif (defined(__GNUC__) && !(defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC)) \
&& (__GNUC__ * 100 + __GNUC_MINOR__) >= 406) || defined(__clang__)
#pragma GCC diagnostic pop
#endif
#endif // !defined(BOOST_SCOPE_ENABLE_WARNINGS)

View File

@@ -0,0 +1,49 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* https://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2023 Andrey Semashev
*/
#if !defined(BOOST_SCOPE_ENABLE_WARNINGS)
#if defined(_MSC_VER) && !defined(__clang__)
#pragma warning(push, 3)
// unreferenced formal parameter
#pragma warning(disable: 4100)
// conditional expression is constant
#pragma warning(disable: 4127)
// function marked as __forceinline not inlined
#pragma warning(disable: 4714)
// decorated name length exceeded, name was truncated
#pragma warning(disable: 4503)
// qualifier applied to function type has no meaning; ignored
#pragma warning(disable: 4180)
// qualifier applied to reference type; ignored
#pragma warning(disable: 4181)
// unreachable code
#pragma warning(disable: 4702)
// destructor never returns, potential memory leak
#pragma warning(disable: 4722)
#elif (defined(__GNUC__) && !(defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC)) \
&& (__GNUC__ * 100 + __GNUC_MINOR__) >= 406) || defined(__clang__)
// Note: clang-cl goes here as well, as it seems to support gcc-style warning control pragmas.
#pragma GCC diagnostic push
// unused parameter 'arg'
#pragma GCC diagnostic ignored "-Wunused-parameter"
// unused function 'foo'
#pragma GCC diagnostic ignored "-Wunused-function"
#if defined(__clang__)
// template argument uses unnamed type
#pragma clang diagnostic ignored "-Wunnamed-type-template-args"
#endif // defined(__clang__)
#endif
#endif // !defined(BOOST_SCOPE_ENABLE_WARNINGS)

View File

@@ -0,0 +1,66 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* https://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2023 Andrey Semashev
*/
/*!
* \file scope/detail/is_nonnull_default_constructible.hpp
*
* This header contains definition of \c is_nonnull_default_constructible
* and \c is_nothrow_nonnull_default_constructible type traits. The type
* traits are useful for preventing default-construction of pointers to
* functions where a default-constructed function object is expected.
* Without it, default- or value-constructing a pointer to function would
* produce a function object that is not callable.
*/
#ifndef BOOST_SCOPE_DETAIL_IS_NONNULL_DEFAULT_CONSTRUCTIBLE_HPP_INCLUDED_
#define BOOST_SCOPE_DETAIL_IS_NONNULL_DEFAULT_CONSTRUCTIBLE_HPP_INCLUDED_
#include <type_traits>
#include <boost/scope/detail/config.hpp>
#include <boost/scope/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace scope {
namespace detail {
//! The type trait checks if \c T is not a pointer and is default-constructible
template< typename T >
struct is_nonnull_default_constructible :
public std::is_default_constructible< T >
{
};
template< typename T >
struct is_nonnull_default_constructible< T* > :
public std::false_type
{
};
//! The type trait checks if \c T is not a pointer and is nothrow-default-constructible
template< typename T >
struct is_nothrow_nonnull_default_constructible :
public std::is_nothrow_default_constructible< T >
{
};
template< typename T >
struct is_nothrow_nonnull_default_constructible< T* > :
public std::false_type
{
};
} // namespace detail
} // namespace scope
} // namespace boost
#include <boost/scope/detail/footer.hpp>
#endif // BOOST_SCOPE_DETAIL_IS_NONNULL_DEFAULT_CONSTRUCTIBLE_HPP_INCLUDED_

View File

@@ -0,0 +1,49 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* https://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2023 Andrey Semashev
*/
/*!
* \file scope/detail/is_not_like.hpp
*
* This header contains definition of \c is_not_like type trait.
*/
#ifndef BOOST_SCOPE_DETAIL_IS_NOT_LIKE_HPP_INCLUDED_
#define BOOST_SCOPE_DETAIL_IS_NOT_LIKE_HPP_INCLUDED_
#include <type_traits>
#include <boost/scope/detail/config.hpp>
#include <boost/scope/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace scope {
namespace detail {
//! The type trait checks if \c T is not a possibly cv-reference-qualified specialization of \c Template
template< typename T, template< typename... > class Template >
struct is_not_like : public std::true_type { };
template< typename T, template< typename... > class Template >
struct is_not_like< T&, Template > : public is_not_like< T, Template > { };
template< template< typename... > class Template, typename... Ts >
struct is_not_like< Template< Ts... >, Template > : public std::false_type { };
template< template< typename... > class Template, typename... Ts >
struct is_not_like< const Template< Ts... >, Template > : public std::false_type { };
template< template< typename... > class Template, typename... Ts >
struct is_not_like< volatile Template< Ts... >, Template > : public std::false_type { };
template< template< typename... > class Template, typename... Ts >
struct is_not_like< const volatile Template< Ts... >, Template > : public std::false_type { };
} // namespace detail
} // namespace scope
} // namespace boost
#include <boost/scope/detail/footer.hpp>
#endif // BOOST_SCOPE_DETAIL_IS_NOT_LIKE_HPP_INCLUDED_

View File

@@ -0,0 +1,52 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* https://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2022 Andrey Semashev
*/
/*!
* \file scope/detail/move_or_copy_assign_ref.hpp
*
* This header contains definition of \c move_or_copy_assign_ref type trait.
*/
#ifndef BOOST_SCOPE_DETAIL_MOVE_OR_COPY_ASSIGN_REF_HPP_INCLUDED_
#define BOOST_SCOPE_DETAIL_MOVE_OR_COPY_ASSIGN_REF_HPP_INCLUDED_
#include <type_traits>
#include <boost/scope/detail/config.hpp>
#include <boost/scope/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace scope {
namespace detail {
//! The type trait produces an rvalue reference to \a From if \a To has a non-throwing assignment from a \a From rvalue and an lvalue reference otherwise.
template< typename From, typename To = From >
struct move_or_copy_assign_ref
{
using type = typename std::conditional<
std::is_nothrow_assignable< To, From >::value,
From&&,
From const&
>::type;
};
template< typename From, typename To >
struct move_or_copy_assign_ref< From&, To >
{
using type = From&;
};
} // namespace detail
} // namespace scope
} // namespace boost
#include <boost/scope/detail/footer.hpp>
#endif // BOOST_SCOPE_DETAIL_MOVE_OR_COPY_ASSIGN_REF_HPP_INCLUDED_

View File

@@ -0,0 +1,52 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* https://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2022 Andrey Semashev
*/
/*!
* \file scope/detail/move_or_copy_construct_ref.hpp
*
* This header contains definition of \c move_or_copy_construct_ref type trait.
*/
#ifndef BOOST_SCOPE_DETAIL_MOVE_OR_COPY_CONSTRUCT_REF_HPP_INCLUDED_
#define BOOST_SCOPE_DETAIL_MOVE_OR_COPY_CONSTRUCT_REF_HPP_INCLUDED_
#include <type_traits>
#include <boost/scope/detail/config.hpp>
#include <boost/scope/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace scope {
namespace detail {
//! The type trait produces an rvalue reference to \a From if \a To has a non-throwing constructor from a \a From rvalue and an lvalue reference otherwise.
template< typename From, typename To = From >
struct move_or_copy_construct_ref
{
using type = typename std::conditional<
std::is_nothrow_constructible< To, From >::value,
From&&,
From const&
>::type;
};
template< typename From, typename To >
struct move_or_copy_construct_ref< From&, To >
{
using type = From&;
};
} // namespace detail
} // namespace scope
} // namespace boost
#include <boost/scope/detail/footer.hpp>
#endif // BOOST_SCOPE_DETAIL_MOVE_OR_COPY_CONSTRUCT_REF_HPP_INCLUDED_

View File

@@ -0,0 +1,53 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* https://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2023 Andrey Semashev
*/
/*!
* \file scope/detail/type_traits/conjunction.hpp
*
* This header contains definition of \c conjunction type trait.
*/
#ifndef BOOST_SCOPE_DETAIL_TYPE_TRAITS_CONJUNCTION_HPP_INCLUDED_
#define BOOST_SCOPE_DETAIL_TYPE_TRAITS_CONJUNCTION_HPP_INCLUDED_
#include <type_traits>
#include <boost/scope/detail/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if (defined(__cpp_lib_logical_traits) && (__cpp_lib_logical_traits >= 201510l)) || \
(defined(BOOST_MSSTL_VERSION) && (BOOST_MSSTL_VERSION >= 140) && (_MSC_FULL_VER >= 190023918) && (BOOST_CXX_VERSION >= 201703l))
namespace boost {
namespace scope {
namespace detail {
using std::conjunction;
} // namespace detail
} // namespace scope
} // namespace boost
#else
#include <boost/type_traits/conjunction.hpp>
namespace boost {
namespace scope {
namespace detail {
using boost::conjunction;
} // namespace detail
} // namespace scope
} // namespace boost
#endif
#endif // BOOST_SCOPE_DETAIL_TYPE_TRAITS_CONJUNCTION_HPP_INCLUDED_

View File

@@ -0,0 +1,53 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* https://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2023 Andrey Semashev
*/
/*!
* \file scope/detail/type_traits/disjunction.hpp
*
* This header contains definition of \c disjunction type trait.
*/
#ifndef BOOST_SCOPE_DETAIL_TYPE_TRAITS_DISJUNCTION_HPP_INCLUDED_
#define BOOST_SCOPE_DETAIL_TYPE_TRAITS_DISJUNCTION_HPP_INCLUDED_
#include <type_traits>
#include <boost/scope/detail/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if (defined(__cpp_lib_logical_traits) && (__cpp_lib_logical_traits >= 201510l)) || \
(defined(BOOST_MSSTL_VERSION) && (BOOST_MSSTL_VERSION >= 140) && (_MSC_FULL_VER >= 190023918) && (BOOST_CXX_VERSION >= 201703l))
namespace boost {
namespace scope {
namespace detail {
using std::disjunction;
} // namespace detail
} // namespace scope
} // namespace boost
#else
#include <boost/type_traits/disjunction.hpp>
namespace boost {
namespace scope {
namespace detail {
using boost::disjunction;
} // namespace detail
} // namespace scope
} // namespace boost
#endif
#endif // BOOST_SCOPE_DETAIL_TYPE_TRAITS_DISJUNCTION_HPP_INCLUDED_

View File

@@ -0,0 +1,53 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* https://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2023 Andrey Semashev
*/
/*!
* \file scope/detail/type_traits/is_final.hpp
*
* This header contains definition of \c is_final type trait.
*/
#ifndef BOOST_SCOPE_DETAIL_TYPE_TRAITS_IS_FINAL_HPP_INCLUDED_
#define BOOST_SCOPE_DETAIL_TYPE_TRAITS_IS_FINAL_HPP_INCLUDED_
#include <type_traits>
#include <boost/scope/detail/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if (defined(__cpp_lib_is_final) && (__cpp_lib_is_final >= 201402l)) || \
(defined(BOOST_MSSTL_VERSION) && (BOOST_MSSTL_VERSION >= 140) && (BOOST_CXX_VERSION >= 201402l))
namespace boost {
namespace scope {
namespace detail {
using std::is_final;
} // namespace detail
} // namespace scope
} // namespace boost
#else
#include <boost/type_traits/is_final.hpp>
namespace boost {
namespace scope {
namespace detail {
using boost::is_final;
} // namespace detail
} // namespace scope
} // namespace boost
#endif
#endif // BOOST_SCOPE_DETAIL_TYPE_TRAITS_IS_FINAL_HPP_INCLUDED_

View File

@@ -0,0 +1,65 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* https://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2023 Andrey Semashev
*/
/*!
* \file scope/detail/type_traits/is_invocable.hpp
*
* This header contains definition of \c is_invocable type trait.
*/
#ifndef BOOST_SCOPE_DETAIL_TYPE_TRAITS_IS_INVOCABLE_HPP_INCLUDED_
#define BOOST_SCOPE_DETAIL_TYPE_TRAITS_IS_INVOCABLE_HPP_INCLUDED_
#include <type_traits>
#include <boost/scope/detail/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if (defined(__cpp_lib_is_invocable) && (__cpp_lib_is_invocable >= 201703l)) || \
(defined(BOOST_MSSTL_VERSION) && (BOOST_MSSTL_VERSION >= 140) && (BOOST_CXX_VERSION >= 201703l))
namespace boost {
namespace scope {
namespace detail {
using std::is_invocable;
} // namespace detail
} // namespace scope
} // namespace boost
#else
#include <utility> // std::declval
namespace boost {
namespace scope {
namespace detail {
// A simplified implementation that does not support member function pointers
template< typename Func, typename... Args >
struct is_invocable_impl
{
template< typename F = Func, typename = decltype(std::declval< F >()(std::declval< Args >()...)) >
static std::true_type _check_invocable(int);
static std::false_type _check_invocable(...);
using type = decltype(is_invocable_impl::_check_invocable(0));
};
template< typename Func, typename... Args >
struct is_invocable : public is_invocable_impl< Func, Args... >::type { };
} // namespace detail
} // namespace scope
} // namespace boost
#endif
#endif // BOOST_SCOPE_DETAIL_TYPE_TRAITS_IS_INVOCABLE_HPP_INCLUDED_

View File

@@ -0,0 +1,70 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* https://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2023 Andrey Semashev
*/
/*!
* \file scope/detail/type_traits/is_nothrow_invocable.hpp
*
* This header contains definition of \c is_nothrow_invocable type trait.
*/
#ifndef BOOST_SCOPE_DETAIL_TYPE_TRAITS_IS_NOTHROW_INVOCABLE_HPP_INCLUDED_
#define BOOST_SCOPE_DETAIL_TYPE_TRAITS_IS_NOTHROW_INVOCABLE_HPP_INCLUDED_
#include <type_traits>
#include <boost/scope/detail/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if (defined(__cpp_lib_is_invocable) && (__cpp_lib_is_invocable >= 201703l)) || \
(defined(BOOST_MSSTL_VERSION) && (BOOST_MSSTL_VERSION >= 140) && (BOOST_CXX_VERSION >= 201703l))
namespace boost {
namespace scope {
namespace detail {
using std::is_nothrow_invocable;
} // namespace detail
} // namespace scope
} // namespace boost
#else
#include <utility> // std::declval
#include <boost/scope/detail/type_traits/is_invocable.hpp>
namespace boost {
namespace scope {
namespace detail {
template< bool, typename Func, typename... Args >
struct is_nothrow_invocable_impl
{
using type = std::false_type;
};
template< typename Func, typename... Args >
struct is_nothrow_invocable_impl< true, Func, Args... >
{
using type = std::integral_constant< bool, noexcept(std::declval< Func >()(std::declval< Args >()...)) >;
};
template< typename Func, typename... Args >
struct is_nothrow_invocable :
public is_nothrow_invocable_impl< detail::is_invocable< Func, Args... >::value, Func, Args... >::type
{
};
} // namespace detail
} // namespace scope
} // namespace boost
#endif
#endif // BOOST_SCOPE_DETAIL_TYPE_TRAITS_IS_NOTHROW_INVOCABLE_HPP_INCLUDED_

View File

@@ -0,0 +1,53 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* https://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2023 Andrey Semashev
*/
/*!
* \file scope/detail/type_traits/is_nothrow_swappable.hpp
*
* This header contains definition of \c is_nothrow_swappable type trait.
*/
#ifndef BOOST_SCOPE_DETAIL_TYPE_TRAITS_IS_NOTHROW_SWAPPABLE_HPP_INCLUDED_
#define BOOST_SCOPE_DETAIL_TYPE_TRAITS_IS_NOTHROW_SWAPPABLE_HPP_INCLUDED_
#include <type_traits>
#include <boost/scope/detail/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if (defined(__cpp_lib_is_swappable) && (__cpp_lib_is_swappable >= 201603l)) || \
(defined(BOOST_MSSTL_VERSION) && (BOOST_MSSTL_VERSION >= 140) && (_MSC_FULL_VER >= 190024210) && (BOOST_CXX_VERSION >= 201703l))
namespace boost {
namespace scope {
namespace detail {
using std::is_nothrow_swappable;
} // namespace detail
} // namespace scope
} // namespace boost
#else
#include <boost/type_traits/is_nothrow_swappable.hpp>
namespace boost {
namespace scope {
namespace detail {
using boost::is_nothrow_swappable;
} // namespace detail
} // namespace scope
} // namespace boost
#endif
#endif // BOOST_SCOPE_DETAIL_TYPE_TRAITS_IS_NOTHROW_SWAPPABLE_HPP_INCLUDED_

View File

@@ -0,0 +1,53 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* https://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2023 Andrey Semashev
*/
/*!
* \file scope/detail/type_traits/is_swappable.hpp
*
* This header contains definition of \c is_swappable type trait.
*/
#ifndef BOOST_SCOPE_DETAIL_TYPE_TRAITS_IS_SWAPPABLE_HPP_INCLUDED_
#define BOOST_SCOPE_DETAIL_TYPE_TRAITS_IS_SWAPPABLE_HPP_INCLUDED_
#include <type_traits>
#include <boost/scope/detail/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if (defined(__cpp_lib_is_swappable) && (__cpp_lib_is_swappable >= 201603l)) || \
(defined(BOOST_MSSTL_VERSION) && (BOOST_MSSTL_VERSION >= 140) && (_MSC_FULL_VER >= 190024210) && (BOOST_CXX_VERSION >= 201703l))
namespace boost {
namespace scope {
namespace detail {
using std::is_swappable;
} // namespace detail
} // namespace scope
} // namespace boost
#else
#include <boost/type_traits/is_swappable.hpp>
namespace boost {
namespace scope {
namespace detail {
using boost::is_swappable;
} // namespace detail
} // namespace scope
} // namespace boost
#endif
#endif // BOOST_SCOPE_DETAIL_TYPE_TRAITS_IS_SWAPPABLE_HPP_INCLUDED_

View File

@@ -0,0 +1,53 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* https://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2023 Andrey Semashev
*/
/*!
* \file scope/detail/type_traits/negation.hpp
*
* This header contains definition of \c negation type trait.
*/
#ifndef BOOST_SCOPE_DETAIL_TYPE_TRAITS_NEGATION_HPP_INCLUDED_
#define BOOST_SCOPE_DETAIL_TYPE_TRAITS_NEGATION_HPP_INCLUDED_
#include <type_traits>
#include <boost/scope/detail/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if (defined(__cpp_lib_logical_traits) && (__cpp_lib_logical_traits >= 201510l)) || \
(defined(BOOST_MSSTL_VERSION) && (BOOST_MSSTL_VERSION >= 140) && (_MSC_FULL_VER >= 190023918) && (BOOST_CXX_VERSION >= 201703l))
namespace boost {
namespace scope {
namespace detail {
using std::negation;
} // namespace detail
} // namespace scope
} // namespace boost
#else
#include <boost/type_traits/negation.hpp>
namespace boost {
namespace scope {
namespace detail {
using boost::negation;
} // namespace detail
} // namespace scope
} // namespace boost
#endif
#endif // BOOST_SCOPE_DETAIL_TYPE_TRAITS_NEGATION_HPP_INCLUDED_

View File

@@ -0,0 +1,103 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* https://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2023 Andrey Semashev
*/
/*!
* \file scope/error_code_checker.hpp
*
* This header contains definition of \c error_code_checker type.
*/
#ifndef BOOST_SCOPE_ERROR_CODE_CHECKER_HPP_INCLUDED_
#define BOOST_SCOPE_ERROR_CODE_CHECKER_HPP_INCLUDED_
#include <boost/core/addressof.hpp>
#include <boost/scope/detail/config.hpp>
#include <boost/scope/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace scope {
/*!
* \brief A predicate for checking whether an error code indicates error.
*
* The predicate captures a reference to an external error code object, which it
* tests for an error indication when called. The error code object must remain
* valid for the whole lifetime duration of the predicate.
*
* For an error code object `ec`, an expression `!ec` must be valid, never throw exceptions,
* and return a value contextually convertible to `bool`. If the returned value converts
* to `false`, then this is taken as an error indication, and the predicate returns `true`.
* Otherwise, the predicate returns `false`.
*
* A few examples of error code types:
*
* \li `std::error_code` or `boost::system::error_code`,
* \li `std::expected`, `boost::outcome_v2::basic_outcome` or `boost::outcome_v2::basic_result`,
* \li `int`, where the value of 0 indicates no error,
* \li `bool`, where the value of `false` indicates no error,
* \li `T*`, where a null pointer indicates no error.
*
* \tparam ErrorCode Error code type.
*/
template< typename ErrorCode >
class error_code_checker
{
public:
//! Predicate result type
using result_type = bool;
private:
ErrorCode* m_error_code;
public:
/*!
* \brief Constructs the predicate.
*
* Upon construction, the predicate saves a reference to the external error code object.
* The referenced object must remain valid for the whole lifetime duration of the predicate.
*
* **Throws:** Nothing.
*/
explicit error_code_checker(ErrorCode& ec) noexcept :
m_error_code(boost::addressof(ec))
{
}
/*!
* \brief Checks if the error code indicates error.
*
* **Throws:** Nothing.
*
* \returns As if `!!ec`, where `ec` is the error code object passed to the predicate constructor.
*/
result_type operator()() const noexcept
{
return !!(*m_error_code);
}
};
/*!
* \brief Creates a predicate for checking whether an exception is being thrown
*
* **Throws:** Nothing.
*/
template< typename ErrorCode >
inline error_code_checker< ErrorCode > check_error_code(ErrorCode& ec) noexcept
{
return error_code_checker< ErrorCode >(ec);
}
} // namespace scope
} // namespace boost
#include <boost/scope/detail/footer.hpp>
#endif // BOOST_SCOPE_ERROR_CODE_CHECKER_HPP_INCLUDED_

View File

@@ -0,0 +1,106 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* https://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2023 Andrey Semashev
*/
/*!
* \file scope/exception_checker.hpp
*
* This header contains definition of \c exception_checker type.
*/
#ifndef BOOST_SCOPE_EXCEPTION_CHECKER_HPP_INCLUDED_
#define BOOST_SCOPE_EXCEPTION_CHECKER_HPP_INCLUDED_
#include <boost/assert.hpp>
#include <boost/scope/detail/config.hpp>
#include <boost/core/uncaught_exceptions.hpp>
#include <boost/scope/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace scope {
/*!
* \brief A predicate for checking whether an exception is being thrown.
*
* On construction, the predicate captures the current number of uncaught exceptions,
* which it then compares with the number of uncaught exceptions at the point when it
* is called. If the number increased then a new exception is detected and the predicate
* returns \c true.
*
* \note This predicate is designed for a specific use case with scope guards created on
* the stack. It is incompatible with C++20 coroutines and similar facilities (e.g.
* fibers and userspace context switching), where the thread of execution may be
* suspended after the predicate captures the number of uncaught exceptions and
* then resumed in a different context, where the number of uncaught exceptions
* has changed. Similarly, it is incompatible with usage patterns where the predicate
* is cached after construction and is invoked after the thread has left the scope
* where the predicate was constructed (e.g. when the predicate is stored as a class
* data member or a namespace-scope variable).
*/
class exception_checker
{
public:
//! Predicate result type
using result_type = bool;
private:
unsigned int m_uncaught_count;
public:
/*!
* \brief Constructs the predicate.
*
* Upon construction, the predicate saves the current number of uncaught exceptions.
* This information will be used when calling the predicate to detect if a new
* exception is being thrown.
*
* **Throws:** Nothing.
*/
exception_checker() noexcept :
m_uncaught_count(boost::core::uncaught_exceptions())
{
}
/*!
* \brief Checks if an exception is being thrown.
*
* **Throws:** Nothing.
*
* \returns \c true if the number of uncaught exceptions at the point of call is
* greater than that at the point of construction of the predicate,
* otherwise \c false.
*/
result_type operator()() const noexcept
{
const unsigned int uncaught_count = boost::core::uncaught_exceptions();
// If this assertion fails, the predicate is likely being used in an unsupported
// way, where it is called in a different scope or thread context from where
// it was constructed.
BOOST_ASSERT((uncaught_count - m_uncaught_count) <= 1u);
return uncaught_count > m_uncaught_count;
}
};
/*!
* \brief Creates a predicate for checking whether an exception is being thrown
*
* **Throws:** Nothing.
*/
inline exception_checker check_exception() noexcept
{
return exception_checker();
}
} // namespace scope
} // namespace boost
#include <boost/scope/detail/footer.hpp>
#endif // BOOST_SCOPE_EXCEPTION_CHECKER_HPP_INCLUDED_

View File

@@ -0,0 +1,82 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* https://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2023 Andrey Semashev
*/
/*!
* \file scope/fd_deleter.hpp
*
* This header contains definition of a deleter function object for
* POSIX-like file descriptors for use with \c unique_resource.
*/
#ifndef BOOST_SCOPE_FD_DELETER_HPP_INCLUDED_
#define BOOST_SCOPE_FD_DELETER_HPP_INCLUDED_
#include <boost/scope/detail/config.hpp>
#if !defined(BOOST_WINDOWS)
#include <unistd.h>
#if defined(hpux) || defined(_hpux) || defined(__hpux)
#include <cerrno>
#endif
#else // !defined(BOOST_WINDOWS)
#include <io.h>
#endif // !defined(BOOST_WINDOWS)
#include <boost/scope/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace scope {
//! POSIX-like file descriptor deleter
struct fd_deleter
{
using result_type = void;
//! Closes the file descriptor
result_type operator() (int fd) const noexcept
{
#if !defined(BOOST_WINDOWS)
#if defined(hpux) || defined(_hpux) || defined(__hpux)
// Some systems don't close the file descriptor in case if the thread is interrupted by a signal and close(2) returns EINTR.
// Other (most) systems do close the file descriptor even when when close(2) returns EINTR, and attempting to close it
// again could close a different file descriptor that was opened by a different thread.
//
// Future POSIX standards will likely fix this by introducing posix_close (see https://www.austingroupbugs.net/view.php?id=529)
// and prohibiting returning EINTR from close(2), but we still have to support older systems where this new behavior is not available and close(2)
// behaves differently between systems.
int res;
while (true)
{
res = ::close(fd);
if (BOOST_UNLIKELY(res < 0))
{
int err = errno;
if (err == EINTR)
continue;
}
break;
}
#else
::close(fd);
#endif
#else // !defined(BOOST_WINDOWS)
::_close(fd);
#endif // !defined(BOOST_WINDOWS)
}
};
} // namespace scope
} // namespace boost
#include <boost/scope/detail/footer.hpp>
#endif // BOOST_SCOPE_FD_DELETER_HPP_INCLUDED_

View File

@@ -0,0 +1,49 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* https://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2023 Andrey Semashev
*/
/*!
* \file scope/fd_resource_traits.hpp
*
* This header contains definition of \c unique_resource traits
* for compatibility with POSIX-like file descriptors.
*/
#ifndef BOOST_SCOPE_FD_RESOURCE_TRAITS_HPP_INCLUDED_
#define BOOST_SCOPE_FD_RESOURCE_TRAITS_HPP_INCLUDED_
#include <boost/scope/detail/config.hpp>
#include <boost/scope/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace scope {
//! POSIX-like file descriptor resource traits
struct fd_resource_traits
{
//! Creates a default fd value
static int make_default() noexcept
{
return -1;
}
//! Tests if the fd is allocated (valid)
static bool is_allocated(int fd) noexcept
{
return fd >= 0;
}
};
} // namespace scope
} // namespace boost
#include <boost/scope/detail/footer.hpp>
#endif // BOOST_SCOPE_FD_RESOURCE_TRAITS_HPP_INCLUDED_

View File

@@ -0,0 +1,560 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* https://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2023 Andrey Semashev
*/
/*!
* \file scope/scope_exit.hpp
*
* This header contains definition of \c scope_exit template.
*/
#ifndef BOOST_SCOPE_SCOPE_EXIT_HPP_INCLUDED_
#define BOOST_SCOPE_SCOPE_EXIT_HPP_INCLUDED_
#include <type_traits>
#include <boost/scope/detail/config.hpp>
#include <boost/scope/detail/is_not_like.hpp>
#include <boost/scope/detail/compact_storage.hpp>
#include <boost/scope/detail/move_or_copy_construct_ref.hpp>
#include <boost/scope/detail/is_nonnull_default_constructible.hpp>
#include <boost/scope/detail/type_traits/conjunction.hpp>
#include <boost/scope/detail/type_traits/is_invocable.hpp>
#include <boost/scope/detail/type_traits/is_nothrow_invocable.hpp>
#include <boost/scope/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace scope {
template< typename Func, typename Cond >
class scope_exit;
namespace detail {
// Workaround for clang < 5.0 which can't pass scope_exit as a template template parameter from within scope_exit definition
template< typename T >
using is_not_like_scope_exit = detail::is_not_like< T, scope_exit >;
//! The scope guard used to invoke the condition and action functions in case of exception during scope guard construction
template< typename Func, typename Cond >
class init_guard
{
private:
Func& m_func;
Cond& m_cond;
bool m_active;
public:
init_guard(Func& func, Cond& cond, bool active) noexcept :
m_func(func),
m_cond(cond),
m_active(active)
{
}
init_guard(init_guard const&) = delete;
init_guard& operator= (init_guard const&) = delete;
~init_guard()
noexcept(detail::conjunction<
detail::is_nothrow_invocable< Func& >,
detail::is_nothrow_invocable< Cond& >
>::value)
{
if (m_active && m_cond())
m_func();
}
Func&& get_func() noexcept
{
return static_cast< Func&& >(m_func);
}
Cond&& get_cond() noexcept
{
return static_cast< Cond&& >(m_cond);
}
void deactivate() noexcept
{
m_active = false;
}
};
} // namespace detail
/*!
* \brief A predicate that always returns \c true.
*
* This predicate can be used as the default condition function object for
* \c scope_exit and similar scope guards.
*/
class always_true
{
public:
//! Predicate result type
using result_type = bool;
/*!
* **Throws:** Nothing.
*
* \returns \c true.
*/
result_type operator()() const noexcept
{
return true;
}
};
/*!
* \brief Scope exit guard that conditionally invokes a function upon leaving the scope.
*
* The scope guard wraps two function objects: the scope guard action and
* a condition for invoking the action. Both function objects must be
* callable with no arguments and can be one of:
*
* \li A user-defined class with a public `operator()`.
* \li An lvalue reference to such class.
* \li An lvalue reference or pointer to function taking no arguments.
*
* The condition function object `operator()` must return a value
* contextually convertible to \c true, if the action function object
* is allowed to be executed, and \c false otherwise. Additionally,
* the condition function object `operator()` must not throw, as
* otherwise the action function object may not be called.
*
* The condition function object is optional, and if not specified in
* template parameters, the scope guard will operate as if the condition
* always returns \c true.
*
* The scope guard can be in either active or inactive state. By default,
* the constructed scope guard is active. When active, and condition
* function object returns \c true, the scope guard invokes the wrapped
* action function object on destruction. Otherwise, the scope guard
* does not call the wrapped action function object.
*
* The scope guard can be made inactive by moving-from the scope guard
* or calling `set_active(false)`. An inactive scope guard can be made
* active by calling `set_active(true)`. If a moved-from scope guard
* is active on destruction, the behavior is undefined.
*
* \tparam Func Scope guard action function object type.
* \tparam Cond Scope guard condition function object type.
*/
template< typename Func, typename Cond = always_true >
class scope_exit
{
//! \cond
private:
struct func_holder :
public detail::compact_storage< Func >
{
using func_base = detail::compact_storage< Func >;
template<
typename F,
typename C,
typename = typename std::enable_if< std::is_constructible< Func, F >::value >::type
>
explicit func_holder(F&& func, C&& cond, bool active, std::true_type) noexcept :
func_base(static_cast< F&& >(func))
{
}
template<
typename F,
typename C,
typename = typename std::enable_if< std::is_constructible< Func, F >::value >::type
>
explicit func_holder(F&& func, C&& cond, bool active, std::false_type) :
func_holder(detail::init_guard< F, C >(func, cond, active))
{
}
private:
template< typename F, typename C >
explicit func_holder(detail::init_guard< F, C >&& init) :
func_base(init.get_func())
{
init.deactivate();
}
};
struct cond_holder :
public detail::compact_storage< Cond >
{
using cond_base = detail::compact_storage< Cond >;
template<
typename C,
typename = typename std::enable_if< std::is_constructible< Cond, C >::value >::type
>
explicit cond_holder(C&& cond, Func& func, bool active, std::true_type) noexcept :
cond_base(static_cast< C&& >(cond))
{
}
template<
typename C,
typename = typename std::enable_if< std::is_constructible< Cond, C >::value >::type
>
explicit cond_holder(C&& cond, Func& func, bool active, std::false_type) :
cond_holder(detail::init_guard< Func&, C >(func, cond, active))
{
}
private:
template< typename C >
explicit cond_holder(detail::init_guard< Func&, C >&& init) :
cond_base(init.get_cond())
{
init.deactivate();
}
};
struct data :
public func_holder,
public cond_holder
{
bool m_active;
template<
typename F,
typename C,
typename = typename std::enable_if< detail::conjunction<
std::is_constructible< func_holder, F, C, bool, typename std::is_nothrow_constructible< Func, F >::type >,
std::is_constructible< cond_holder, C, Func&, bool, typename std::is_nothrow_constructible< Cond, C >::type >
>::value >::type
>
explicit data(F&& func, C&& cond, bool active)
noexcept(detail::conjunction< std::is_nothrow_constructible< Func, F >, std::is_nothrow_constructible< Cond, C > >::value) :
func_holder(static_cast< F&& >(func), static_cast< C&& >(cond), active, typename std::is_nothrow_constructible< Func, F >::type()),
cond_holder(static_cast< C&& >(cond), func_holder::get(), active, typename std::is_nothrow_constructible< Cond, C >::type()),
m_active(active)
{
}
Func& get_func() noexcept
{
return func_holder::get();
}
Func const& get_func() const noexcept
{
return func_holder::get();
}
Cond& get_cond() noexcept
{
return cond_holder::get();
}
Cond const& get_cond() const noexcept
{
return cond_holder::get();
}
bool deactivate() noexcept
{
bool active = m_active;
m_active = false;
return active;
}
};
data m_data;
//! \endcond
public:
/*!
* \brief Constructs a scope guard with a given callable action function object.
*
* **Requires:** \c Func is constructible from \a func. \c Cond is nothrow default-constructible
* and is not a pointer to function.
*
* \note The requirement for \c Cond default constructor to be non-throwing is to allow for
* the condition function object to be called in case if constructing either function
* object throws.
*
* **Effects:** Constructs the scope guard as if by calling
* `scope_exit(std::forward< F >(func), Cond(), active)`.
*
* **Throws:** Nothing, unless construction of the function objects throw.
*
* \param func The callable action function object to invoke on destruction.
* \param active Indicates whether the scope guard should be active upon construction.
*
* \post `this->active() == active`
*/
template<
typename F
//! \cond
, typename = typename std::enable_if< detail::conjunction<
detail::is_nothrow_nonnull_default_constructible< Cond >,
std::is_constructible<
data,
typename detail::move_or_copy_construct_ref< F, Func >::type,
typename detail::move_or_copy_construct_ref< Cond >::type,
bool
>,
detail::is_not_like_scope_exit< F >
>::value >::type
//! \endcond
>
explicit scope_exit(F&& func, bool active = true)
noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(
std::is_nothrow_constructible<
data,
typename detail::move_or_copy_construct_ref< F, Func >::type,
typename detail::move_or_copy_construct_ref< Cond >::type,
bool
>::value
)) :
m_data
(
static_cast< typename detail::move_or_copy_construct_ref< F, Func >::type >(func),
static_cast< typename detail::move_or_copy_construct_ref< Cond >::type >(Cond()),
active
)
{
}
/*!
* \brief Constructs a scope guard with a given callable action and condition function objects.
*
* **Requires:** \c Func is constructible from \a func. \c Cond is constructible from \a cond.
*
* **Effects:** If \c Func is nothrow constructible from `F&&` then constructs \c Func from
* `std::forward< F >(func)`, otherwise constructs from `func`. If \c Cond is
* nothrow constructible from `C&&` then constructs \c Cond from
* `std::forward< C >(cond)`, otherwise constructs from `cond`.
*
* If \c Func or \c Cond construction throws and \a active is \c true, invokes
* \a cond and, if it returns \c true, \a func before returning with the exception.
*
* **Throws:** Nothing, unless construction of the function objects throw.
*
* \param func The callable action function object to invoke on destruction.
* \param cond The callable condition function object.
* \param active Indicates whether the scope guard should be active upon construction.
*
* \post `this->active() == active`
*/
template<
typename F,
typename C
//! \cond
, typename = typename std::enable_if< detail::conjunction<
detail::is_invocable< C const& >,
std::is_constructible<
data,
typename detail::move_or_copy_construct_ref< F, Func >::type,
typename detail::move_or_copy_construct_ref< C, Cond >::type,
bool
>
>::value >::type
//! \endcond
>
explicit scope_exit(F&& func, C&& cond, bool active = true)
noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(
std::is_nothrow_constructible<
data,
typename detail::move_or_copy_construct_ref< F, Func >::type,
typename detail::move_or_copy_construct_ref< C, Cond >::type,
bool
>::value
)) :
m_data
(
static_cast< typename detail::move_or_copy_construct_ref< F, Func >::type >(func),
static_cast< typename detail::move_or_copy_construct_ref< C, Cond >::type >(cond),
active
)
{
}
/*!
* \brief Move-constructs a scope guard.
*
* **Requires:** \c Func and \c Cond are nothrow move-constructible or copy-constructible.
*
* **Effects:** If \c Func is nothrow move-constructible then move-constructs \c Func from
* a member of \a that, otherwise copy-constructs \c Func. If \c Cond is nothrow
* move-constructible then move-constructs \c Cond from a member of \a that,
* otherwise copy-constructs \c Cond.
*
* If \c Func or \c Cond construction throws and `that.active() == true`, invokes
* \c Cond object stored in \a that and, if it returns \c true, \a Func object
* (either the newly constructed one, if its construction succeeded, or the original
* one stored in \a that) before returning with the exception.
*
* If the construction succeeds, marks \a that as inactive.
*
* **Throws:** Nothing, unless move-construction of the function objects throw.
*
* \param that Move source.
*
* \post `that.active() == false`
*/
//! \cond
template<
bool Requires = std::is_constructible<
data,
typename detail::move_or_copy_construct_ref< Func >::type,
typename detail::move_or_copy_construct_ref< Cond >::type,
bool
>::value,
typename = typename std::enable_if< Requires >::type
>
//! \endcond
scope_exit(scope_exit&& that)
noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(
std::is_nothrow_constructible<
data,
typename detail::move_or_copy_construct_ref< Func >::type,
typename detail::move_or_copy_construct_ref< Cond >::type,
bool
>::value
)) :
m_data
(
static_cast< typename detail::move_or_copy_construct_ref< Func >::type >(that.m_data.get_func()),
static_cast< typename detail::move_or_copy_construct_ref< Cond >::type >(that.m_data.get_cond()),
that.m_data.deactivate()
)
{
}
scope_exit& operator= (scope_exit&&) = delete;
scope_exit(scope_exit const&) = delete;
scope_exit& operator= (scope_exit const&) = delete;
/*!
* \brief If `active() == true`, and invoking the condition function object returns \c true, invokes
* the wrapped callable action function object. Destroys the function objects.
*
* **Throws:** Nothing, unless invoking a function object throws.
*/
~scope_exit()
noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(
detail::conjunction<
detail::is_nothrow_invocable< Func& >,
detail::is_nothrow_invocable< Cond& >
>::value
))
{
if (BOOST_LIKELY(m_data.m_active && m_data.get_cond()()))
m_data.get_func()();
}
/*!
* \brief Returns \c true if the scope guard is active, otherwise \c false.
*
* \note This method does not call the condition function object specified on construction.
*
* **Throws:** Nothing.
*/
bool active() const noexcept
{
return m_data.m_active;
}
/*!
* \brief Activates or deactivates the scope guard.
*
* **Throws:** Nothing.
*
* \param active The active status to set.
*
* \post `this->active() == active`
*/
void set_active(bool active) noexcept
{
m_data.m_active = active;
}
};
#if !defined(BOOST_NO_CXX17_DEDUCTION_GUIDES)
template< typename Func >
explicit scope_exit(Func) -> scope_exit< Func >;
template< typename Func >
explicit scope_exit(Func, bool) -> scope_exit< Func >;
template< typename Func, typename Cond >
explicit scope_exit(Func, Cond) -> scope_exit< Func, Cond >;
template< typename Func, typename Cond >
explicit scope_exit(Func, Cond, bool) -> scope_exit< Func, Cond >;
#endif // !defined(BOOST_NO_CXX17_DEDUCTION_GUIDES)
/*!
* \brief Creates a scope guard with a given action function object.
*
* **Effects:** Constructs a scope guard as if by calling
* `scope_exit< std::decay_t< F > >(std::forward< F >(func), active)`.
*
* \param func The callable action function object to invoke on destruction.
* \param active Indicates whether the scope guard should be active upon construction.
*/
template< typename F >
inline scope_exit< typename std::decay< F >::type > make_scope_exit(F&& func, bool active = true)
noexcept(std::is_nothrow_constructible<
scope_exit< typename std::decay< F >::type >,
F,
bool
>::value)
{
return scope_exit< typename std::decay< F >::type >(static_cast< F&& >(func), active);
}
/*!
* \brief Creates a conditional scope guard with given callable function objects.
*
* **Effects:** Constructs a scope guard as if by calling
* `scope_exit< std::decay_t< F >, std::decay_t< C > >(
* std::forward< F >(func), std::forward< C >(cond), active)`.
*
* \param func The callable action function object to invoke on destruction.
* \param cond The callable condition function object.
* \param active Indicates whether the scope guard should be active upon construction.
*/
template< typename F, typename C >
inline
#if !defined(BOOST_SCOPE_DOXYGEN)
typename std::enable_if<
std::is_constructible<
scope_exit< typename std::decay< F >::type, typename std::decay< C >::type >,
F,
C,
bool
>::value,
scope_exit< typename std::decay< F >::type, typename std::decay< C >::type >
>::type
#else
scope_exit< typename std::decay< F >::type, typename std::decay< C >::type >
#endif
make_scope_exit(F&& func, C&& cond, bool active = true)
noexcept(std::is_nothrow_constructible<
scope_exit< typename std::decay< F >::type, typename std::decay< C >::type >,
F,
C,
bool
>::value)
{
return scope_exit< typename std::decay< F >::type, typename std::decay< C >::type >(static_cast< F&& >(func), static_cast< C&& >(cond), active);
}
} // namespace scope
} // namespace boost
#include <boost/scope/detail/footer.hpp>
#endif // BOOST_SCOPE_SCOPE_EXIT_HPP_INCLUDED_

View File

@@ -0,0 +1,265 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* https://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2022 Andrey Semashev
*/
/*!
* \file scope/scope_fail.hpp
*
* This header contains definition of \c scope_fail template.
*/
#ifndef BOOST_SCOPE_SCOPE_FAIL_HPP_INCLUDED_
#define BOOST_SCOPE_SCOPE_FAIL_HPP_INCLUDED_
#include <type_traits>
#include <boost/scope/detail/config.hpp>
#include <boost/scope/exception_checker.hpp>
#include <boost/scope/scope_exit.hpp>
#include <boost/scope/detail/is_not_like.hpp>
#include <boost/scope/detail/type_traits/conjunction.hpp>
#include <boost/scope/detail/type_traits/is_invocable.hpp>
#include <boost/scope/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace scope {
template< typename Func, typename Cond >
class scope_fail;
namespace detail {
// Workaround for clang < 5.0 which can't pass scope_fail as a template template parameter from within scope_fail definition
template< typename T >
using is_not_like_scope_fail = detail::is_not_like< T, scope_fail >;
} // namespace detail
/*!
* \brief Scope exit guard that invokes a function upon leaving the scope, if
* a failure condition is satisfied.
*
* The scope guard wraps two function objects: the scope guard action and
* a failure condition for invoking the action. Both function objects must
* be callable with no arguments and can be one of:
*
* \li A user-defined class with a public `operator()`.
* \li An lvalue reference to such class.
* \li An lvalue reference or pointer to function taking no arguments.
*
* The condition function object `operator()` must return a value
* contextually convertible to \c true, if the failure is detected and the
* action function object is allowed to be executed, and \c false otherwise.
* Additionally, the failure condition function object `operator()` must not
* throw, as otherwise the action function object may not be called. If not
* specified, the default failure condition checks whether the scope is left
* due to an exception - the action function object will not be called if
* the scope is left normally.
*
* \sa scope_exit
* \sa scope_success
*
* \tparam Func Scope guard action function object type.
* \tparam Cond Scope guard failure condition function object type.
*/
template< typename Func, typename Cond = exception_checker >
class scope_fail :
public scope_exit< Func, Cond >
{
//! \cond
private:
using base_type = scope_exit< Func, Cond >;
//! \endcond
public:
/*!
* \brief Constructs a scope guard with a given callable function object.
*
* **Requires:** \c Func is constructible from \a func. \c Cond is nothrow default-constructible.
*
* **Effects:** Constructs the scope guard as if by calling
* `scope_fail(std::forward< F >(func), Cond(), active)`.
*
* **Throws:** Nothing, unless construction of the function objects throw.
*
* \param func The callable action function object to invoke on destruction.
* \param active Indicates whether the scope guard should be active upon construction.
*
* \post `this->active() == active`
*/
template<
typename F
//! \cond
, typename = typename std::enable_if< detail::conjunction<
std::is_constructible< base_type, F, bool >,
detail::is_not_like_scope_fail< F >
>::value >::type
//! \endcond
>
explicit scope_fail(F&& func, bool active = true)
noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(std::is_nothrow_constructible< base_type, F, bool >::value)) :
base_type(static_cast< F&& >(func), active)
{
}
/*!
* \brief Constructs a scope guard with a given callable action and failure condition function objects.
*
* **Requires:** \c Func is constructible from \a func. \c Cond is constructible from \a cond.
*
* **Effects:** If \c Func is nothrow constructible from `F&&` then constructs \c Func from
* `std::forward< F >(func)`, otherwise constructs from `func`. If \c Cond is
* nothrow constructible from `C&&` then constructs \c Cond from
* `std::forward< C >(cond)`, otherwise constructs from `cond`.
*
* If \c Func or \c Cond construction throws and \a active is \c true, invokes
* \a cond and, if it returns \c true, \a func before returning with the exception.
*
* **Throws:** Nothing, unless construction of the function objects throw.
*
* \param func The callable action function object to invoke on destruction.
* \param cond The callable failure condition function object.
* \param active Indicates whether the scope guard should be active upon construction.
*
* \post `this->active() == active`
*/
template<
typename F,
typename C
//! \cond
, typename = typename std::enable_if< std::is_constructible< base_type, F, C, bool >::value >::type
//! \endcond
>
explicit scope_fail(F&& func, C&& cond, bool active = true)
noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(std::is_nothrow_constructible< base_type, F, C, bool >::value)) :
base_type(static_cast< F&& >(func), static_cast< C&& >(cond), active)
{
}
/*!
* \brief Move-constructs a scope guard.
*
* **Requires:** \c Func and \c Cond are nothrow move-constructible or copy-constructible.
*
* **Effects:** If \c Func is nothrow move-constructible then move-constructs \c Func from
* a member of \a that, otherwise copy-constructs \c Func. If \c Cond is nothrow
* move-constructible then move-constructs \c Cond from a member of \a that,
* otherwise copy-constructs \c Cond.
*
* If \c Func or \c Cond construction throws and `that.active() == true`, invokes
* \c Cond object stored in \a that and, if it returns \c true, \a Func object
* (either the newly constructed one, if its construction succeeded, or the original
* one stored in \a that) before returning with the exception.
*
* If the construction succeeds, marks \a that as inactive.
*
* **Throws:** Nothing, unless move-construction of the function objects throw.
*
* \param that Move source.
*
* \post `that.active() == false`
*/
//! \cond
template<
bool Requires = std::is_move_constructible< base_type >::value,
typename = typename std::enable_if< Requires >::type
>
//! \endcond
scope_fail(scope_fail&& that)
noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(std::is_nothrow_move_constructible< base_type >::value)) :
base_type(static_cast< base_type&& >(that))
{
}
scope_fail& operator= (scope_fail&&) = delete;
scope_fail(scope_fail const&) = delete;
scope_fail& operator= (scope_fail const&) = delete;
};
#if !defined(BOOST_NO_CXX17_DEDUCTION_GUIDES)
template< typename Func >
explicit scope_fail(Func) -> scope_fail< Func >;
template< typename Func >
explicit scope_fail(Func, bool) -> scope_fail< Func >;
template<
typename Func,
typename Cond,
typename = typename std::enable_if< detail::is_invocable< Cond const& >::value >::type
>
explicit scope_fail(Func, Cond) -> scope_fail< Func, Cond >;
template<
typename Func,
typename Cond,
typename = typename std::enable_if< detail::is_invocable< Cond const& >::value >::type
>
explicit scope_fail(Func, Cond, bool) -> scope_fail< Func, Cond >;
#endif // !defined(BOOST_NO_CXX17_DEDUCTION_GUIDES)
/*!
* \brief Creates a scope fail guard with a given action function object.
*
* **Effects:** Constructs a scope guard as if by calling
* `scope_fail< std::decay_t< F > >(std::forward< F >(func), active)`.
*
* \param func The callable function object to invoke on destruction.
* \param active Indicates whether the scope guard should be active upon construction.
*/
template< typename F >
inline scope_fail< typename std::decay< F >::type > make_scope_fail(F&& func, bool active = true)
noexcept(std::is_nothrow_constructible<
scope_fail< typename std::decay< F >::type >,
F,
bool
>::value)
{
return scope_fail< typename std::decay< F >::type >(static_cast< F&& >(func), active);
}
/*!
* \brief Creates a scope fail with given callable function objects.
*
* **Effects:** Constructs a scope guard as if by calling
* `scope_fail< std::decay_t< F >, std::decay_t< C > >(
* std::forward< F >(func), std::forward< C >(cond), active)`.
*
* \param func The callable action function object to invoke on destruction.
* \param cond The callable failure condition function object.
* \param active Indicates whether the scope guard should be active upon construction.
*/
template< typename F, typename C >
inline
#if !defined(BOOST_SCOPE_DOXYGEN)
typename std::enable_if<
detail::is_invocable< C const& >::value,
scope_fail< typename std::decay< F >::type, typename std::decay< C >::type >
>::type
#else
scope_fail< typename std::decay< F >::type, typename std::decay< C >::type >
#endif
make_scope_fail(F&& func, C&& cond, bool active = true)
noexcept(std::is_nothrow_constructible<
scope_fail< typename std::decay< F >::type, typename std::decay< C >::type >,
F,
C,
bool
>::value)
{
return scope_fail< typename std::decay< F >::type, typename std::decay< C >::type >(static_cast< F&& >(func), static_cast< C&& >(cond), active);
}
} // namespace scope
} // namespace boost
#include <boost/scope/detail/footer.hpp>
#endif // BOOST_SCOPE_SCOPE_FAIL_HPP_INCLUDED_

View File

@@ -0,0 +1,309 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* https://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2022 Andrey Semashev
*/
/*!
* \file scope/scope_success.hpp
*
* This header contains definition of \c scope_success template.
*/
#ifndef BOOST_SCOPE_SCOPE_SUCCESS_HPP_INCLUDED_
#define BOOST_SCOPE_SCOPE_SUCCESS_HPP_INCLUDED_
#include <type_traits>
#include <boost/scope/detail/config.hpp>
#include <boost/scope/exception_checker.hpp>
#include <boost/scope/scope_exit.hpp>
#include <boost/scope/detail/is_not_like.hpp>
#include <boost/scope/detail/type_traits/conjunction.hpp>
#include <boost/scope/detail/type_traits/is_invocable.hpp>
#include <boost/scope/detail/type_traits/is_nothrow_invocable.hpp>
#include <boost/scope/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace scope {
template< typename Func, typename Cond >
class scope_success;
namespace detail {
// Workaround for clang < 5.0 which can't pass scope_success as a template template parameter from within scope_success definition
template< typename T >
using is_not_like_scope_success = detail::is_not_like< T, scope_success >;
template< typename Func >
class logical_not;
template< typename T >
using is_not_like_logical_not = detail::is_not_like< T, logical_not >;
template< typename Func >
class logical_not
{
public:
using result_type = bool;
private:
Func m_func;
public:
template<
bool Requires = std::is_default_constructible< Func >::value,
typename = typename std::enable_if< Requires >::type
>
logical_not() noexcept(std::is_nothrow_default_constructible< Func >::value) :
m_func()
{
}
template<
typename F,
typename = typename std::enable_if< detail::conjunction<
std::is_constructible< Func, F >,
detail::is_not_like_logical_not< F >
>::value >::type
>
explicit logical_not(F&& func) noexcept(std::is_nothrow_constructible< Func, F >::value) :
m_func(static_cast< F&& >(func))
{
}
result_type operator()() const noexcept(detail::is_nothrow_invocable< Func const& >::value)
{
return !m_func();
}
};
} // namespace detail
/*!
* \brief Scope exit guard that invokes a function upon leaving the scope, if
* a failure condition is not satisfied.
*
* The scope guard wraps two function objects: the scope guard action and
* a failure condition for invoking the action. Both function objects must
* be callable with no arguments and can be one of:
*
* \li A user-defined class with a public `operator()`.
* \li An lvalue reference to such class.
* \li An lvalue reference or pointer to function taking no arguments.
*
* The condition function object `operator()` must return a value
* contextually convertible to \c true, if the failure is detected and the
* action function object is not allowed to be executed, and \c false otherwise.
* Additionally, the failure condition function object `operator()` must not
* throw, as otherwise the action function object may not be called. If not
* specified, the default failure condition checks whether the scope is left
* due to an exception - the action function object will only be called if
* the scope is left normally.
*
* \sa scope_exit
* \sa scope_fail
*
* \tparam Func Scope guard action function object type.
* \tparam Cond Scope guard failure condition function object type.
*/
template< typename Func, typename Cond = exception_checker >
class scope_success :
public scope_exit< Func, detail::logical_not< Cond > >
{
//! \cond
private:
using base_type = scope_exit< Func, detail::logical_not< Cond > >;
//! \endcond
public:
/*!
* \brief Constructs a scope guard with a given callable function object.
*
* **Requires:** \c Func is constructible from \a func. \c Cond is nothrow default-constructible.
*
* **Effects:** Constructs the scope guard as if by calling
* `scope_success(std::forward< F >(func), Cond(), active)`.
*
* **Throws:** Nothing, unless construction of the function objects throw.
*
* \param func The callable action function object to invoke on destruction.
* \param active Indicates whether the scope guard should be active upon construction.
*
* \post `this->active() == active`
*/
template<
typename F
//! \cond
, typename = typename std::enable_if< detail::conjunction<
std::is_constructible< base_type, F, bool >,
detail::is_not_like_scope_success< F >
>::value >::type
//! \endcond
>
explicit scope_success(F&& func, bool active = true)
noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(std::is_nothrow_constructible< base_type, F, bool >::value)) :
base_type(static_cast< F&& >(func), active)
{
}
/*!
* \brief Constructs a scope guard with a given callable action and failure condition function objects.
*
* **Requires:** \c Func is constructible from \a func. \c Cond is constructible from \a cond.
*
* **Effects:** If \c Func is nothrow constructible from `F&&` then constructs \c Func from
* `std::forward< F >(func)`, otherwise constructs from `func`. If \c Cond is
* nothrow constructible from `C&&` then constructs \c Cond from
* `std::forward< C >(cond)`, otherwise constructs from `cond`.
*
* If \c Func or \c Cond construction throws and \a active is \c true, invokes
* \a cond and, if it returns \c true, \a func before returning with the exception.
*
* **Throws:** Nothing, unless construction of the function objects throw.
*
* \param func The callable action function object to invoke on destruction.
* \param cond The callable failure condition function object.
* \param active Indicates whether the scope guard should be active upon construction.
*
* \post `this->active() == active`
*/
template<
typename F,
typename C
//! \cond
, typename = typename std::enable_if< std::is_constructible< base_type, F, C, bool >::value >::type
//! \endcond
>
explicit scope_success(F&& func, C&& cond, bool active = true)
noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(std::is_nothrow_constructible< base_type, F, C, bool >::value)) :
base_type(static_cast< F&& >(func), static_cast< C&& >(cond), active)
{
}
/*!
* \brief Move-constructs a scope guard.
*
* **Requires:** \c Func and \c Cond are nothrow move-constructible or copy-constructible.
*
* **Effects:** If \c Func is nothrow move-constructible then move-constructs \c Func from
* a member of \a that, otherwise copy-constructs \c Func. If \c Cond is nothrow
* move-constructible then move-constructs \c Cond from a member of \a that,
* otherwise copy-constructs \c Cond.
*
* If \c Func or \c Cond construction throws and `that.active() == true`, invokes
* \c Cond object stored in \a that and, if it returns \c true, \a Func object
* (either the newly constructed one, if its construction succeeded, or the original
* one stored in \a that) before returning with the exception.
*
* If the construction succeeds, marks \a that as inactive.
*
* **Throws:** Nothing, unless move-construction of the function objects throw.
*
* \param that Move source.
*
* \post `that.active() == false`
*/
//! \cond
template<
bool Requires = std::is_move_constructible< base_type >::value,
typename = typename std::enable_if< Requires >::type
>
//! \endcond
scope_success(scope_success&& that)
noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(std::is_nothrow_move_constructible< base_type >::value)) :
base_type(static_cast< base_type&& >(that))
{
}
scope_success& operator= (scope_success&&) = delete;
scope_success(scope_success const&) = delete;
scope_success& operator= (scope_success const&) = delete;
};
#if !defined(BOOST_NO_CXX17_DEDUCTION_GUIDES)
template< typename Func >
explicit scope_success(Func) -> scope_success< Func >;
template< typename Func >
explicit scope_success(Func, bool) -> scope_success< Func >;
template<
typename Func,
typename Cond,
typename = typename std::enable_if< detail::is_invocable< Cond const& >::value >::type
>
explicit scope_success(Func, Cond) -> scope_success< Func, Cond >;
template<
typename Func,
typename Cond,
typename = typename std::enable_if< detail::is_invocable< Cond const& >::value >::type
>
explicit scope_success(Func, Cond, bool) -> scope_success< Func, Cond >;
#endif // !defined(BOOST_NO_CXX17_DEDUCTION_GUIDES)
/*!
* \brief Creates a scope fail guard with a given action function object.
*
* **Effects:** Constructs a scope guard as if by calling
* `scope_success< std::decay_t< F > >(std::forward< F >(func), active)`.
*
* \param func The callable function object to invoke on destruction.
* \param active Indicates whether the scope guard should be active upon construction.
*/
template< typename F >
inline scope_success< typename std::decay< F >::type > make_scope_success(F&& func, bool active = true)
noexcept(std::is_nothrow_constructible<
scope_success< typename std::decay< F >::type >,
F,
bool
>::value)
{
return scope_success< typename std::decay< F >::type >(static_cast< F&& >(func), active);
}
/*!
* \brief Creates a scope fail with given callable function objects.
*
* **Effects:** Constructs a scope guard as if by calling
* `scope_success< std::decay_t< F >, std::decay_t< C > >(
* std::forward< F >(func), std::forward< C >(cond), active)`.
*
* \param func The callable action function object to invoke on destruction.
* \param cond The callable failure condition function object.
* \param active Indicates whether the scope guard should be active upon construction.
*/
template< typename F, typename C >
inline
#if !defined(BOOST_SCOPE_DOXYGEN)
typename std::enable_if<
detail::is_invocable< C const& >::value,
scope_success< typename std::decay< F >::type, typename std::decay< C >::type >
>::type
#else
scope_success< typename std::decay< F >::type, typename std::decay< C >::type >
#endif
make_scope_success(F&& func, C&& cond, bool active = true)
noexcept(std::is_nothrow_constructible<
scope_success< typename std::decay< F >::type, typename std::decay< C >::type >,
F,
C,
bool
>::value)
{
return scope_success< typename std::decay< F >::type, typename std::decay< C >::type >(static_cast< F&& >(func), static_cast< C&& >(cond), active);
}
} // namespace scope
} // namespace boost
#include <boost/scope/detail/footer.hpp>
#endif // BOOST_SCOPE_SCOPE_SUCCESS_HPP_INCLUDED_

View File

@@ -0,0 +1,38 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* https://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2023 Andrey Semashev
*/
/*!
* \file scope/unique_fd.hpp
*
* This header contains definition of \c unique_fd type.
*/
#ifndef BOOST_SCOPE_UNIQUE_FD_HPP_INCLUDED_
#define BOOST_SCOPE_UNIQUE_FD_HPP_INCLUDED_
#include <boost/scope/detail/config.hpp>
#include <boost/scope/unique_resource.hpp>
#include <boost/scope/fd_deleter.hpp>
#include <boost/scope/fd_resource_traits.hpp>
#include <boost/scope/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace scope {
//! Unique POSIX-like file descriptor resource
using unique_fd = unique_resource< int, fd_deleter, fd_resource_traits >;
} // namespace scope
} // namespace boost
#include <boost/scope/detail/footer.hpp>
#endif // BOOST_SCOPE_UNIQUE_FD_HPP_INCLUDED_

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,46 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* https://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2022 Andrey Semashev
*/
/*!
* \file scope/unique_resource_fwd.hpp
*
* This header contains forward declaration of \c unique_resource template.
*/
#ifndef BOOST_SCOPE_UNIQUE_RESOURCE_FWD_HPP_INCLUDED_
#define BOOST_SCOPE_UNIQUE_RESOURCE_FWD_HPP_INCLUDED_
#include <type_traits>
#include <boost/scope/detail/config.hpp>
#include <boost/scope/detail/move_or_copy_construct_ref.hpp>
#include <boost/scope/detail/type_traits/conjunction.hpp>
#include <boost/scope/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace scope {
template< typename Resource, typename Deleter, typename Traits = void >
class unique_resource;
template< typename Resource, typename Deleter, typename Invalid = typename std::decay< Resource >::type >
unique_resource< typename std::decay< Resource >::type, typename std::decay< Deleter >::type >
make_unique_resource_checked(Resource&& res, Invalid const& invalid, Deleter&& del)
noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(detail::conjunction<
std::is_nothrow_constructible< typename std::decay< Resource >::type, typename detail::move_or_copy_construct_ref< Resource, typename std::decay< Resource >::type >::type >,
std::is_nothrow_constructible< typename std::decay< Deleter >::type, typename detail::move_or_copy_construct_ref< Deleter, typename std::decay< Deleter >::type >::type >
>::value));
} // namespace scope
} // namespace boost
#include <boost/scope/detail/footer.hpp>
#endif // BOOST_SCOPE_UNIQUE_RESOURCE_FWD_HPP_INCLUDED_