diff options
author | Alexander Smirnov <alex@ydb.tech> | 2024-10-16 12:11:24 +0000 |
---|---|---|
committer | Alexander Smirnov <alex@ydb.tech> | 2024-10-16 12:11:24 +0000 |
commit | 40811e93f3fdf9342a9295369994012420fac548 (patch) | |
tree | a8d85e094a9c21e10aa250f537c101fc2016a049 /contrib/restricted/boost/scope | |
parent | 30ebe5357bb143648c6be4d151ecd4944af81ada (diff) | |
parent | 28a0c4a9f297064538a018c512cd9bbd00a1a35d (diff) | |
download | ydb-40811e93f3fdf9342a9295369994012420fac548.tar.gz |
Merge branch 'rightlib' into mergelibs-241016-1210
Diffstat (limited to 'contrib/restricted/boost/scope')
33 files changed, 4597 insertions, 0 deletions
diff --git a/contrib/restricted/boost/scope/.yandex_meta/devtools.copyrights.report b/contrib/restricted/boost/scope/.yandex_meta/devtools.copyrights.report new file mode 100644 index 0000000000..25c80d389e --- /dev/null +++ b/contrib/restricted/boost/scope/.yandex_meta/devtools.copyrights.report @@ -0,0 +1,91 @@ +# File format ($ symbol means the beginning of a line): +# +# $ # this message +# $ # ======================= +# $ # comments (all commentaries should starts with some number of spaces and # symbol) +# $ IGNORE_FILES {file1.ext1} {file2.ext2} - (optional) ignore listed files when generating license macro and credits +# $ RENAME {original license id} TO {new license id} # user comments - (optional) use {new license id} instead {original license id} in ya.make files +# $ # user comments +# $ +# ${action} {license id} {license text hash} +# $BELONGS ./ya/make/file/relative/path/1/ya.make ./ya/make/2/ya.make +# ${all_file_action} filename +# $ # user commentaries (many lines) +# $ generated description - files with this license, license text... (some number of lines that starts with some number of spaces, do not modify) +# ${action} {license spdx} {license text hash} +# $BELONGS ./ya/make/file/relative/path/3/ya.make +# ${all_file_action} filename +# $ # user commentaries +# $ generated description +# $ ... +# +# You can modify action, all_file_action and add commentaries +# Available actions: +# keep - keep license in contrib and use in credits +# skip - skip license +# remove - remove all files with this license +# rename - save license text/links into licenses texts file, but not store SPDX into LINCENSE macro. You should store correct license id into devtools.license.spdx.txt file +# +# {all file action} records will be generated when license text contains filename that exists on filesystem (in contrib directory) +# We suppose that that files can contain some license info +# Available all file actions: +# FILE_IGNORE - ignore file (do nothing) +# FILE_INCLUDE - include all file data into licenses text file +# ======================= + +KEEP COPYRIGHT_SERVICE_LABEL 3244b00e8ab273a03f19b20a64c26a96 +BELONGS ya.make + License text: + * Copyright (c) 2023 Andrey Semashev + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/scope/detail/config.hpp [6:6] + include/boost/scope/detail/footer.hpp [6:6] + include/boost/scope/detail/header.hpp [6:6] + include/boost/scope/detail/is_nonnull_default_constructible.hpp [6:6] + include/boost/scope/detail/is_not_like.hpp [6:6] + include/boost/scope/detail/type_traits/conjunction.hpp [6:6] + include/boost/scope/detail/type_traits/disjunction.hpp [6:6] + include/boost/scope/detail/type_traits/is_final.hpp [6:6] + include/boost/scope/detail/type_traits/is_invocable.hpp [6:6] + include/boost/scope/detail/type_traits/is_nothrow_invocable.hpp [6:6] + include/boost/scope/detail/type_traits/is_nothrow_swappable.hpp [6:6] + include/boost/scope/detail/type_traits/is_swappable.hpp [6:6] + include/boost/scope/detail/type_traits/negation.hpp [6:6] + include/boost/scope/error_code_checker.hpp [6:6] + include/boost/scope/exception_checker.hpp [6:6] + include/boost/scope/fd_deleter.hpp [6:6] + include/boost/scope/fd_resource_traits.hpp [6:6] + include/boost/scope/scope_exit.hpp [6:6] + include/boost/scope/unique_fd.hpp [6:6] + +KEEP COPYRIGHT_SERVICE_LABEL 3f6ec3343e75c2c0c0e1e8956ffabc65 +BELONGS ya.make + License text: + * Copyright (c) 2022-2024 Andrey Semashev + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/scope/defer.hpp [6:6] + include/boost/scope/unique_resource.hpp [6:6] + +KEEP COPYRIGHT_SERVICE_LABEL 45666b61e7d8667b41556a93c064e0e8 +BELONGS ya.make + License text: + * Copyright (c) 2022 Andrey Semashev + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/scope/detail/compact_storage.hpp [6:6] + include/boost/scope/detail/move_or_copy_assign_ref.hpp [6:6] + include/boost/scope/detail/move_or_copy_construct_ref.hpp [6:6] + include/boost/scope/scope_fail.hpp [6:6] + include/boost/scope/scope_success.hpp [6:6] + include/boost/scope/unique_resource_fwd.hpp [6:6] diff --git a/contrib/restricted/boost/scope/.yandex_meta/devtools.licenses.report b/contrib/restricted/boost/scope/.yandex_meta/devtools.licenses.report new file mode 100644 index 0000000000..6fe13bd0ea --- /dev/null +++ b/contrib/restricted/boost/scope/.yandex_meta/devtools.licenses.report @@ -0,0 +1,108 @@ +# File format ($ symbol means the beginning of a line): +# +# $ # this message +# $ # ======================= +# $ # comments (all commentaries should starts with some number of spaces and # symbol) +# $ IGNORE_FILES {file1.ext1} {file2.ext2} - (optional) ignore listed files when generating license macro and credits +# $ RENAME {original license id} TO {new license id} # user comments - (optional) use {new license id} instead {original license id} in ya.make files +# $ # user comments +# $ +# ${action} {license id} {license text hash} +# $BELONGS ./ya/make/file/relative/path/1/ya.make ./ya/make/2/ya.make +# ${all_file_action} filename +# $ # user commentaries (many lines) +# $ generated description - files with this license, license text... (some number of lines that starts with some number of spaces, do not modify) +# ${action} {license spdx} {license text hash} +# $BELONGS ./ya/make/file/relative/path/3/ya.make +# ${all_file_action} filename +# $ # user commentaries +# $ generated description +# $ ... +# +# You can modify action, all_file_action and add commentaries +# Available actions: +# keep - keep license in contrib and use in credits +# skip - skip license +# remove - remove all files with this license +# rename - save license text/links into licenses texts file, but not store SPDX into LINCENSE macro. You should store correct license id into devtools.license.spdx.txt file +# +# {all file action} records will be generated when license text contains filename that exists on filesystem (in contrib directory) +# We suppose that that files can contain some license info +# Available all file actions: +# FILE_IGNORE - ignore file (do nothing) +# FILE_INCLUDE - include all file data into licenses text file +# ======================= + +KEEP BSL-1.0 2077ca9d01c7e6d6029ec1763233c5b0 +BELONGS ya.make + License text: + * 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) + Scancode info: + Original SPDX id: BSL-1.0 + Score : 100.00 + Match type : NOTICE + Links : http://www.boost.org/LICENSE_1_0.txt, http://www.boost.org/users/license.html, https://spdx.org/licenses/BSL-1.0 + Files with this license: + include/boost/scope/defer.hpp [2:4] + include/boost/scope/detail/compact_storage.hpp [2:4] + include/boost/scope/detail/config.hpp [2:4] + include/boost/scope/detail/footer.hpp [2:4] + include/boost/scope/detail/header.hpp [2:4] + include/boost/scope/detail/is_nonnull_default_constructible.hpp [2:4] + include/boost/scope/detail/is_not_like.hpp [2:4] + include/boost/scope/detail/move_or_copy_assign_ref.hpp [2:4] + include/boost/scope/detail/move_or_copy_construct_ref.hpp [2:4] + include/boost/scope/detail/type_traits/conjunction.hpp [2:4] + include/boost/scope/detail/type_traits/disjunction.hpp [2:4] + include/boost/scope/detail/type_traits/is_final.hpp [2:4] + include/boost/scope/detail/type_traits/is_invocable.hpp [2:4] + include/boost/scope/detail/type_traits/is_nothrow_invocable.hpp [2:4] + include/boost/scope/detail/type_traits/is_nothrow_swappable.hpp [2:4] + include/boost/scope/detail/type_traits/is_swappable.hpp [2:4] + include/boost/scope/detail/type_traits/negation.hpp [2:4] + include/boost/scope/error_code_checker.hpp [2:4] + include/boost/scope/exception_checker.hpp [2:4] + include/boost/scope/fd_deleter.hpp [2:4] + include/boost/scope/fd_resource_traits.hpp [2:4] + include/boost/scope/scope_exit.hpp [2:4] + include/boost/scope/scope_fail.hpp [2:4] + include/boost/scope/scope_success.hpp [2:4] + include/boost/scope/unique_fd.hpp [2:4] + include/boost/scope/unique_resource.hpp [2:4] + include/boost/scope/unique_resource_fwd.hpp [2:4] + +KEEP BSL-1.0 2c7a3fa82e66676005cd4ee2608fd7d2 +BELONGS ya.make + Note: matched license text is too long. Read it in the source files. + Scancode info: + Original SPDX id: BSL-1.0 + Score : 100.00 + Match type : TEXT + Links : http://www.boost.org/LICENSE_1_0.txt, http://www.boost.org/users/license.html, https://spdx.org/licenses/BSL-1.0 + Files with this license: + LICENSE [1:23] + +KEEP BSL-1.0 49af97cadb10453f2b05003f793e4adc +BELONGS ya.make + License text: + Distributed under the [Boost Software License, Version 1.0](https://www.boost.org/LICENSE_1_0.txt). + Scancode info: + Original SPDX id: BSL-1.0 + Score : 94.44 + Match type : NOTICE + Links : http://www.boost.org/LICENSE_1_0.txt, http://www.boost.org/users/license.html, https://spdx.org/licenses/BSL-1.0 + Files with this license: + README.md [28:28] + +KEEP BSL-1.0 a5006bb276a0e8fcc0c080cd5a14814e +BELONGS ya.make + Note: matched license text is too long. Read it in the source files. + Scancode info: + Original SPDX id: BSL-1.0 + Score : 55.00 + Match type : NOTICE + Links : http://www.boost.org/LICENSE_1_0.txt, http://www.boost.org/users/license.html, https://spdx.org/licenses/BSL-1.0 + Files with this license: + README.md [17:17] diff --git a/contrib/restricted/boost/scope/.yandex_meta/licenses.list.txt b/contrib/restricted/boost/scope/.yandex_meta/licenses.list.txt new file mode 100644 index 0000000000..6790a8ddab --- /dev/null +++ b/contrib/restricted/boost/scope/.yandex_meta/licenses.list.txt @@ -0,0 +1,48 @@ +====================BSL-1.0==================== + * 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) + + +====================BSL-1.0==================== +* Submit your patches as [pull requests](https://github.com/boostorg/scope/compare) against **develop** branch. Note that by submitting patches you agree to license your modifications under the [Boost Software License, Version 1.0](https://www.boost.org/LICENSE_1_0.txt). + + +====================BSL-1.0==================== +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +====================BSL-1.0==================== +Distributed under the [Boost Software License, Version 1.0](https://www.boost.org/LICENSE_1_0.txt). + +====================COPYRIGHT==================== + * Copyright (c) 2022 Andrey Semashev + + +====================COPYRIGHT==================== + * Copyright (c) 2022-2024 Andrey Semashev + + +====================COPYRIGHT==================== + * Copyright (c) 2023 Andrey Semashev diff --git a/contrib/restricted/boost/scope/LICENSE b/contrib/restricted/boost/scope/LICENSE new file mode 100644 index 0000000000..36b7cd93cd --- /dev/null +++ b/contrib/restricted/boost/scope/LICENSE @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/contrib/restricted/boost/scope/README.md b/contrib/restricted/boost/scope/README.md new file mode 100644 index 0000000000..21bc1f403c --- /dev/null +++ b/contrib/restricted/boost/scope/README.md @@ -0,0 +1,28 @@ +# Boost.Scope + +Boost.Scope provides a number of scope guard utilities and a `unique_resource` wrapper, similar to those described in +[C++ Extensions for Library Fundamentals, Version 3](https://github.com/cplusplus/fundamentals-ts/releases/tag/n4908), +Section 3.3 Scope guard support \[scopeguard\]. The implementation also provides a few non-standard extensions. + +### Directories + +* **doc** - QuickBook documentation sources +* **include** - Interface headers of Boost.Scope +* **test** - Boost.Scope unit tests + +### More information + +* Read the [documentation](https://www.boost.org/libs/scope/). +* [Report bugs](https://github.com/boostorg/scope/issues/new). Be sure to mention Boost version, platform and compiler you're using. A small compilable code sample to reproduce the problem is always good as well. +* Submit your patches as [pull requests](https://github.com/boostorg/scope/compare) against **develop** branch. Note that by submitting patches you agree to license your modifications under the [Boost Software License, Version 1.0](https://www.boost.org/LICENSE_1_0.txt). + +### Build status + +Branch | GitHub Actions| Test Matrix | Dependencies | +:-------------: | --------------| ----------- | ------------ | +[`master`](https://github.com/boostorg/scope/tree/master) | [![GitHub Actions](https://github.com/boostorg/scope/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/boostorg/scope/actions?query=branch%3Amaster) | [![Tests](https://img.shields.io/badge/matrix-master-brightgreen.svg)](https://www.boost.org/development/tests/master/developer/scope.html) | [![Dependencies](https://img.shields.io/badge/deps-master-brightgreen.svg)](https://pdimov.github.io/boostdep-report/master/scope.html) +[`develop`](https://github.com/boostorg/scope/tree/develop) | [![GitHub Actions](https://github.com/boostorg/scope/actions/workflows/ci.yml/badge.svg?branch=develop)](https://github.com/boostorg/scope/actions?query=branch%3Adevelop) | [![Tests](https://img.shields.io/badge/matrix-develop-brightgreen.svg)](https://www.boost.org/development/tests/develop/developer/scope.html) | [![Dependencies](https://img.shields.io/badge/deps-develop-brightgreen.svg)](https://pdimov.github.io/boostdep-report/develop/scope.html) + +### License + +Distributed under the [Boost Software License, Version 1.0](https://www.boost.org/LICENSE_1_0.txt). diff --git a/contrib/restricted/boost/scope/include/boost/scope/defer.hpp b/contrib/restricted/boost/scope/include/boost/scope/defer.hpp new file mode 100644 index 0000000000..988f976536 --- /dev/null +++ b/contrib/restricted/boost/scope/include/boost/scope/defer.hpp @@ -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_ diff --git a/contrib/restricted/boost/scope/include/boost/scope/detail/compact_storage.hpp b/contrib/restricted/boost/scope/include/boost/scope/detail/compact_storage.hpp new file mode 100644 index 0000000000..b619e3f7d3 --- /dev/null +++ b/contrib/restricted/boost/scope/include/boost/scope/detail/compact_storage.hpp @@ -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_ diff --git a/contrib/restricted/boost/scope/include/boost/scope/detail/config.hpp b/contrib/restricted/boost/scope/include/boost/scope/detail/config.hpp new file mode 100644 index 0000000000..26821ea344 --- /dev/null +++ b/contrib/restricted/boost/scope/include/boost/scope/detail/config.hpp @@ -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_ diff --git a/contrib/restricted/boost/scope/include/boost/scope/detail/footer.hpp b/contrib/restricted/boost/scope/include/boost/scope/detail/footer.hpp new file mode 100644 index 0000000000..2d9b12e6ba --- /dev/null +++ b/contrib/restricted/boost/scope/include/boost/scope/detail/footer.hpp @@ -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) diff --git a/contrib/restricted/boost/scope/include/boost/scope/detail/header.hpp b/contrib/restricted/boost/scope/include/boost/scope/detail/header.hpp new file mode 100644 index 0000000000..fc99f16cf1 --- /dev/null +++ b/contrib/restricted/boost/scope/include/boost/scope/detail/header.hpp @@ -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) diff --git a/contrib/restricted/boost/scope/include/boost/scope/detail/is_nonnull_default_constructible.hpp b/contrib/restricted/boost/scope/include/boost/scope/detail/is_nonnull_default_constructible.hpp new file mode 100644 index 0000000000..e6e86474f4 --- /dev/null +++ b/contrib/restricted/boost/scope/include/boost/scope/detail/is_nonnull_default_constructible.hpp @@ -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_ diff --git a/contrib/restricted/boost/scope/include/boost/scope/detail/is_not_like.hpp b/contrib/restricted/boost/scope/include/boost/scope/detail/is_not_like.hpp new file mode 100644 index 0000000000..3f07fa8023 --- /dev/null +++ b/contrib/restricted/boost/scope/include/boost/scope/detail/is_not_like.hpp @@ -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_ diff --git a/contrib/restricted/boost/scope/include/boost/scope/detail/move_or_copy_assign_ref.hpp b/contrib/restricted/boost/scope/include/boost/scope/detail/move_or_copy_assign_ref.hpp new file mode 100644 index 0000000000..0e270f8c1b --- /dev/null +++ b/contrib/restricted/boost/scope/include/boost/scope/detail/move_or_copy_assign_ref.hpp @@ -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_ diff --git a/contrib/restricted/boost/scope/include/boost/scope/detail/move_or_copy_construct_ref.hpp b/contrib/restricted/boost/scope/include/boost/scope/detail/move_or_copy_construct_ref.hpp new file mode 100644 index 0000000000..b3d3796868 --- /dev/null +++ b/contrib/restricted/boost/scope/include/boost/scope/detail/move_or_copy_construct_ref.hpp @@ -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_ diff --git a/contrib/restricted/boost/scope/include/boost/scope/detail/type_traits/conjunction.hpp b/contrib/restricted/boost/scope/include/boost/scope/detail/type_traits/conjunction.hpp new file mode 100644 index 0000000000..497f5721d2 --- /dev/null +++ b/contrib/restricted/boost/scope/include/boost/scope/detail/type_traits/conjunction.hpp @@ -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_ diff --git a/contrib/restricted/boost/scope/include/boost/scope/detail/type_traits/disjunction.hpp b/contrib/restricted/boost/scope/include/boost/scope/detail/type_traits/disjunction.hpp new file mode 100644 index 0000000000..af1532dede --- /dev/null +++ b/contrib/restricted/boost/scope/include/boost/scope/detail/type_traits/disjunction.hpp @@ -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_ diff --git a/contrib/restricted/boost/scope/include/boost/scope/detail/type_traits/is_final.hpp b/contrib/restricted/boost/scope/include/boost/scope/detail/type_traits/is_final.hpp new file mode 100644 index 0000000000..57a2bf255b --- /dev/null +++ b/contrib/restricted/boost/scope/include/boost/scope/detail/type_traits/is_final.hpp @@ -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_ diff --git a/contrib/restricted/boost/scope/include/boost/scope/detail/type_traits/is_invocable.hpp b/contrib/restricted/boost/scope/include/boost/scope/detail/type_traits/is_invocable.hpp new file mode 100644 index 0000000000..987bf1b10b --- /dev/null +++ b/contrib/restricted/boost/scope/include/boost/scope/detail/type_traits/is_invocable.hpp @@ -0,0 +1,63 @@ +/* + * 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 + +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_ diff --git a/contrib/restricted/boost/scope/include/boost/scope/detail/type_traits/is_nothrow_invocable.hpp b/contrib/restricted/boost/scope/include/boost/scope/detail/type_traits/is_nothrow_invocable.hpp new file mode 100644 index 0000000000..5510a5fb0a --- /dev/null +++ b/contrib/restricted/boost/scope/include/boost/scope/detail/type_traits/is_nothrow_invocable.hpp @@ -0,0 +1,69 @@ +/* + * 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 <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_ diff --git a/contrib/restricted/boost/scope/include/boost/scope/detail/type_traits/is_nothrow_swappable.hpp b/contrib/restricted/boost/scope/include/boost/scope/detail/type_traits/is_nothrow_swappable.hpp new file mode 100644 index 0000000000..08e3171655 --- /dev/null +++ b/contrib/restricted/boost/scope/include/boost/scope/detail/type_traits/is_nothrow_swappable.hpp @@ -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_ diff --git a/contrib/restricted/boost/scope/include/boost/scope/detail/type_traits/is_swappable.hpp b/contrib/restricted/boost/scope/include/boost/scope/detail/type_traits/is_swappable.hpp new file mode 100644 index 0000000000..c84a147913 --- /dev/null +++ b/contrib/restricted/boost/scope/include/boost/scope/detail/type_traits/is_swappable.hpp @@ -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_ diff --git a/contrib/restricted/boost/scope/include/boost/scope/detail/type_traits/negation.hpp b/contrib/restricted/boost/scope/include/boost/scope/detail/type_traits/negation.hpp new file mode 100644 index 0000000000..f78f52f22c --- /dev/null +++ b/contrib/restricted/boost/scope/include/boost/scope/detail/type_traits/negation.hpp @@ -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_ diff --git a/contrib/restricted/boost/scope/include/boost/scope/error_code_checker.hpp b/contrib/restricted/boost/scope/include/boost/scope/error_code_checker.hpp new file mode 100644 index 0000000000..1481e14f52 --- /dev/null +++ b/contrib/restricted/boost/scope/include/boost/scope/error_code_checker.hpp @@ -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_ diff --git a/contrib/restricted/boost/scope/include/boost/scope/exception_checker.hpp b/contrib/restricted/boost/scope/include/boost/scope/exception_checker.hpp new file mode 100644 index 0000000000..a46b4801b7 --- /dev/null +++ b/contrib/restricted/boost/scope/include/boost/scope/exception_checker.hpp @@ -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_ diff --git a/contrib/restricted/boost/scope/include/boost/scope/fd_deleter.hpp b/contrib/restricted/boost/scope/include/boost/scope/fd_deleter.hpp new file mode 100644 index 0000000000..92f3ee21f5 --- /dev/null +++ b/contrib/restricted/boost/scope/include/boost/scope/fd_deleter.hpp @@ -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_ diff --git a/contrib/restricted/boost/scope/include/boost/scope/fd_resource_traits.hpp b/contrib/restricted/boost/scope/include/boost/scope/fd_resource_traits.hpp new file mode 100644 index 0000000000..76177979ca --- /dev/null +++ b/contrib/restricted/boost/scope/include/boost/scope/fd_resource_traits.hpp @@ -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_ diff --git a/contrib/restricted/boost/scope/include/boost/scope/scope_exit.hpp b/contrib/restricted/boost/scope/include/boost/scope/scope_exit.hpp new file mode 100644 index 0000000000..0f03ff4c47 --- /dev/null +++ b/contrib/restricted/boost/scope/include/boost/scope/scope_exit.hpp @@ -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_ diff --git a/contrib/restricted/boost/scope/include/boost/scope/scope_fail.hpp b/contrib/restricted/boost/scope/include/boost/scope/scope_fail.hpp new file mode 100644 index 0000000000..a9c2368c57 --- /dev/null +++ b/contrib/restricted/boost/scope/include/boost/scope/scope_fail.hpp @@ -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_ diff --git a/contrib/restricted/boost/scope/include/boost/scope/scope_success.hpp b/contrib/restricted/boost/scope/include/boost/scope/scope_success.hpp new file mode 100644 index 0000000000..a5cd3c160d --- /dev/null +++ b/contrib/restricted/boost/scope/include/boost/scope/scope_success.hpp @@ -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_ diff --git a/contrib/restricted/boost/scope/include/boost/scope/unique_fd.hpp b/contrib/restricted/boost/scope/include/boost/scope/unique_fd.hpp new file mode 100644 index 0000000000..305ad38867 --- /dev/null +++ b/contrib/restricted/boost/scope/include/boost/scope/unique_fd.hpp @@ -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_ diff --git a/contrib/restricted/boost/scope/include/boost/scope/unique_resource.hpp b/contrib/restricted/boost/scope/include/boost/scope/unique_resource.hpp new file mode 100644 index 0000000000..81683c4076 --- /dev/null +++ b/contrib/restricted/boost/scope/include/boost/scope/unique_resource.hpp @@ -0,0 +1,1642 @@ +/* + * 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/unique_resource.hpp + * + * This header contains definition of \c unique_resource template. + */ + +#ifndef BOOST_SCOPE_UNIQUE_RESOURCE_HPP_INCLUDED_ +#define BOOST_SCOPE_UNIQUE_RESOURCE_HPP_INCLUDED_ + +#include <new> // for placement new +#include <type_traits> +#include <boost/core/addressof.hpp> +#include <boost/core/invoke_swap.hpp> +#include <boost/scope/unique_resource_fwd.hpp> +#include <boost/scope/detail/config.hpp> +#include <boost/scope/detail/compact_storage.hpp> +#include <boost/scope/detail/move_or_copy_assign_ref.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/is_swappable.hpp> +#include <boost/scope/detail/type_traits/is_nothrow_swappable.hpp> +#include <boost/scope/detail/type_traits/is_nothrow_invocable.hpp> +#include <boost/scope/detail/type_traits/negation.hpp> +#include <boost/scope/detail/type_traits/conjunction.hpp> +#include <boost/scope/detail/type_traits/disjunction.hpp> +#include <boost/scope/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace scope { + +#if !defined(BOOST_NO_CXX17_FOLD_EXPRESSIONS) && !defined(BOOST_NO_CXX17_AUTO_NONTYPE_TEMPLATE_PARAMS) + +/*! + * \brief Simple resource traits for one or more unallocated resource values. + * + * This class template generates resource traits for `unique_resource` that specify + * one or more unallocated resource values. The first value, specified in the \c DefaultValue + * non-type template parameter, is considered the default. The other values, listed in + * \c UnallocatedValues, are optional. Any resource values other than \c DefaultValue + * or listed in \c UnallocatedValues are considered as allocated. + * + * In order for the generated resource traits to enable optimized implementation of + * `unique_resource`, the resource type must support non-throwing construction and assignment + * from, and comparison for (in)equality with \c DefaultValue or any of the resource + * values listed in \c UnallocatedValues. + */ +template< auto DefaultValue, auto... UnallocatedValues > +struct unallocated_resource +{ + //! Returns the default resource value + static decltype(DefaultValue) make_default() noexcept + { + return DefaultValue; + } + + //! Tests if \a res is an allocated resource value + template< typename Resource > + static bool is_allocated(Resource const& res) noexcept + { + static_assert(noexcept(res != DefaultValue && (... && (res != UnallocatedValues))), + "Invalid unallocated resource value types: comparing resource values with the unallocated values must be noexcept"); + return res != DefaultValue && (... && (res != UnallocatedValues)); + } +}; + +#endif // !defined(BOOST_NO_CXX17_FOLD_EXPRESSIONS) && !defined(BOOST_NO_CXX17_AUTO_NONTYPE_TEMPLATE_PARAMS) + +struct default_resource_t { }; + +//! Keyword representing default, unallocated resource argument +BOOST_INLINE_VARIABLE constexpr default_resource_t default_resource = { }; + +namespace detail { + +// The type trait indicates whether \c T is a possibly qualified \c default_resource_t type +template< typename T > +struct is_default_resource : public std::false_type { }; +template< > +struct is_default_resource< default_resource_t > : public std::true_type { }; +template< > +struct is_default_resource< const default_resource_t > : public std::true_type { }; +template< > +struct is_default_resource< volatile default_resource_t > : public std::true_type { }; +template< > +struct is_default_resource< const volatile default_resource_t > : public std::true_type { }; +template< typename T > +struct is_default_resource< T& > : public is_default_resource< T >::type { }; + +// Lightweight reference wrapper +template< typename T > +class ref_wrapper +{ +private: + T* m_value; + +public: + explicit +#if !defined(BOOST_CORE_NO_CONSTEXPR_ADDRESSOF) + constexpr +#endif + ref_wrapper(T& value) noexcept : + m_value(boost::addressof(value)) + { + } + + ref_wrapper& operator= (T& value) noexcept + { + m_value = boost::addressof(value); + return *this; + } + + ref_wrapper(T&&) = delete; + ref_wrapper& operator= (T&&) = delete; + + operator T& () const noexcept + { + return *m_value; + } + + template< typename... Args > + void operator() (Args&&... args) const noexcept(detail::is_nothrow_invocable< T&, Args&&... >::value) + { + (*m_value)(static_cast< Args&& >(args)...); + } +}; + +template< typename T > +struct wrap_reference +{ + using type = T; +}; + +template< typename T > +struct wrap_reference< T& > +{ + using type = ref_wrapper< T >; +}; + +template< typename Resource, bool UseCompactStorage > +class resource_holder : + public detail::compact_storage< typename wrap_reference< Resource >::type > +{ +public: + using resource_type = Resource; + using internal_resource_type = typename wrap_reference< resource_type >::type; + +private: + using resource_base = detail::compact_storage< internal_resource_type >; + +public: + template< + bool Requires = std::is_default_constructible< internal_resource_type >::value, + typename = typename std::enable_if< Requires >::type + > + constexpr resource_holder() noexcept(std::is_nothrow_default_constructible< internal_resource_type >::value) : + resource_base() + { + } + + template< + typename R, + typename = typename std::enable_if< std::is_constructible< internal_resource_type, R >::value >::type + > + explicit resource_holder(R&& res) noexcept(std::is_nothrow_constructible< internal_resource_type, R >::value) : + resource_base(static_cast< R&& >(res)) + { + } + + template< + typename R, + typename D, + typename = typename std::enable_if< std::is_constructible< internal_resource_type, R >::value >::type + > + explicit resource_holder(R&& res, D&& del, bool allocated) noexcept(std::is_nothrow_constructible< internal_resource_type, R >::value) : + resource_holder(static_cast< R&& >(res), static_cast< D&& >(del), allocated, typename std::is_nothrow_constructible< resource_type, R >::type()) + { + } + + resource_type& get() noexcept + { + return resource_base::get(); + } + + resource_type const& get() const noexcept + { + return resource_base::get(); + } + + internal_resource_type& get_internal() noexcept + { + return resource_base::get(); + } + + internal_resource_type const& get_internal() const noexcept + { + return resource_base::get(); + } + + void move_from(internal_resource_type&& that) noexcept(std::is_nothrow_move_assignable< internal_resource_type >::value) + { + resource_base::get() = static_cast< internal_resource_type&& >(that); + } + +private: + template< typename R, typename D > + explicit resource_holder(R&& res, D&& del, bool allocated, std::true_type) noexcept : + resource_base(static_cast< R&& >(res)) + { + } + + template< typename R, typename D > + explicit resource_holder(R&& res, D&& del, bool allocated, std::false_type) try : + resource_base(res) + { + } + catch (...) + { + if (allocated) + del(res); + } +}; + +template< typename Resource > +class resource_holder< Resource, false > +{ +public: + using resource_type = Resource; + using internal_resource_type = typename wrap_reference< resource_type >::type; + +private: + // Note: Not using compact_storage since we will need to reuse storage for this complete object in move_from + internal_resource_type m_resource; + +public: + template< + bool Requires = std::is_default_constructible< internal_resource_type >::value, + typename = typename std::enable_if< Requires >::type + > + constexpr resource_holder() noexcept(std::is_nothrow_default_constructible< internal_resource_type >::value) : + m_resource() + { + } + + template< + typename R, + typename = typename std::enable_if< std::is_constructible< internal_resource_type, R >::value >::type + > + explicit resource_holder(R&& res) noexcept(std::is_nothrow_constructible< internal_resource_type, R >::value) : + m_resource(static_cast< R&& >(res)) + { + } + + template< + typename R, + typename D, + typename = typename std::enable_if< std::is_constructible< internal_resource_type, R >::value >::type + > + explicit resource_holder(R&& res, D&& del, bool allocated) noexcept(std::is_nothrow_constructible< internal_resource_type, R >::value) : + resource_holder(static_cast< R&& >(res), static_cast< D&& >(del), allocated, typename std::is_nothrow_constructible< resource_type, R >::type()) + { + } + + resource_type& get() noexcept + { + return m_resource; + } + + resource_type const& get() const noexcept + { + return m_resource; + } + + internal_resource_type& get_internal() noexcept + { + return m_resource; + } + + internal_resource_type const& get_internal() const noexcept + { + return m_resource; + } + + void move_from(internal_resource_type&& that) + noexcept(std::is_nothrow_constructible< internal_resource_type, typename detail::move_or_copy_construct_ref< resource_type >::type >::value) + { + internal_resource_type* p = boost::addressof(m_resource); + p->~internal_resource_type(); + new (p) internal_resource_type(static_cast< typename detail::move_or_copy_construct_ref< resource_type >::type >(that)); + } + +private: + template< typename R, typename D > + explicit resource_holder(R&& res, D&& del, bool allocated, std::true_type) noexcept : + m_resource(static_cast< R&& >(res)) + { + } + + template< typename R, typename D > + explicit resource_holder(R&& res, D&& del, bool allocated, std::false_type) try : + m_resource(res) + { + } + catch (...) + { + if (allocated) + del(res); + } +}; + +template< typename Resource, typename Deleter > +class deleter_holder : + public detail::compact_storage< typename wrap_reference< Deleter >::type > +{ +public: + using resource_type = Resource; + using deleter_type = Deleter; + using internal_deleter_type = typename wrap_reference< deleter_type >::type; + +private: + using deleter_base = detail::compact_storage< internal_deleter_type >; + +public: + template< + bool Requires = detail::is_nonnull_default_constructible< internal_deleter_type >::value, + typename = typename std::enable_if< Requires >::type + > + constexpr deleter_holder() noexcept(detail::is_nothrow_nonnull_default_constructible< internal_deleter_type >::value) : + deleter_base() + { + } + + template< + typename D, + typename = typename std::enable_if< std::is_constructible< internal_deleter_type, D >::value >::type + > + explicit deleter_holder(D&& del) noexcept(std::is_nothrow_constructible< internal_deleter_type, D >::value) : + deleter_base(static_cast< D&& >(del)) + { + } + + template< + typename D, + typename = typename std::enable_if< std::is_constructible< internal_deleter_type, D >::value >::type + > + explicit deleter_holder(D&& del, resource_type& res, bool allocated) noexcept(std::is_nothrow_constructible< internal_deleter_type, D >::value) : + deleter_holder(static_cast< D&& >(del), res, allocated, typename std::is_nothrow_constructible< internal_deleter_type, D >::type()) + { + } + + deleter_type& get() noexcept + { + return deleter_base::get(); + } + + deleter_type const& get() const noexcept + { + return deleter_base::get(); + } + + internal_deleter_type& get_internal() noexcept + { + return deleter_base::get(); + } + + internal_deleter_type const& get_internal() const noexcept + { + return deleter_base::get(); + } + +private: + template< typename D > + explicit deleter_holder(D&& del, resource_type& res, bool allocated, std::true_type) noexcept : + deleter_base(static_cast< D&& >(del)) + { + } + + template< typename D > + explicit deleter_holder(D&& del, resource_type& res, bool allocated, std::false_type) try : + deleter_base(del) + { + } + catch (...) + { + if (BOOST_LIKELY(allocated)) + del(res); + } +}; + +/* + * This metafunction indicates whether \c resource_holder should use \c compact_storage + * to optimize storage for the resource object. Its definition must be coherent with + * `resource_holder::move_from` definition and move constructor implementation in + * \c unique_resource_data. + * + * There is one tricky case with \c unique_resource move constructor, when the resource move + * constructor is noexcept and deleter's move and copy constructors are not. It is possible + * that \c unique_resource_data move constructor moves the resource into the object being + * constructed but fails to construct the deleter. In this case we want to move the resource + * back to the original \c unique_resource_data object (which is guaranteed to not throw since + * the resource's move constructor is non-throwing). + * + * However, if we use the move constructor to move the resource back, we need to use placement + * new, and this only lets us create a complete object of the resource type, which prohibits + * the use of \c compact_storage, as it may create the resource object as a base subobject of + * \c compact_storage. Using placement new on a base subobject may corrupt data that is placed + * in the trailing padding bits of the resource type. + * + * To work around this limitation, we also test if move assignment of the resource type is + * also non-throwing (which is reasonable to expect, given that the move constructor is + * non-throwing). If it is, we can avoid having to destroy and move-construct the resource and + * use move-assignment instead. This doesn't require a complete object of the resource type + * and allows us to use \c compact_storage. If move assignment is not noexcept then we have + * to use the move constructor and disable the \c compact_storage optimization. + * + * So this trait has to detect (a) whether we are affected by this tricky case of the + * \c unique_resource move constructor in the first place and (b) whether we can use move + * assignment to move the resource back to the original \c unique_resource object. If we're + * not affected or we can use move assignment then we enable \c compact_storage. + */ +template< typename Resource, typename Deleter > +using use_resource_compact_storage = detail::disjunction< + std::is_nothrow_move_assignable< typename wrap_reference< Resource >::type >, + std::is_nothrow_constructible< typename wrap_reference< Deleter >::type, typename detail::move_or_copy_construct_ref< Deleter >::type >, + detail::negation< std::is_nothrow_constructible< typename wrap_reference< Resource >::type, typename detail::move_or_copy_construct_ref< Resource >::type > > +>; + +template< typename Resource, typename Deleter, typename Traits > +class unique_resource_data : + public detail::resource_holder< Resource, use_resource_compact_storage< Resource, Deleter >::value >, + public detail::deleter_holder< Resource, Deleter > +{ +public: + using resource_type = Resource; + using deleter_type = Deleter; + using traits_type = Traits; + +private: + using resource_holder = detail::resource_holder< resource_type, use_resource_compact_storage< resource_type, deleter_type >::value >; + using deleter_holder = detail::deleter_holder< resource_type, deleter_type >; + using result_of_make_default = decltype(traits_type::make_default()); + +public: + using internal_resource_type = typename resource_holder::internal_resource_type; + using internal_deleter_type = typename deleter_holder::internal_deleter_type; + + static_assert(noexcept(traits_type::make_default()), "Invalid unique_resource resource traits: make_default must be noexcept"); + static_assert(std::is_nothrow_assignable< internal_resource_type&, result_of_make_default >::value, + "Invalid unique_resource resource traits: resource must be nothrow-assignable from the result of make_default"); + static_assert(noexcept(traits_type::is_allocated(std::declval< resource_type const& >())), "Invalid unique_resource resource traits: is_allocated must be noexcept"); + +public: + template< + bool Requires = detail::conjunction< + std::is_constructible< resource_holder, result_of_make_default >, + std::is_default_constructible< deleter_holder > + >::value, + typename = typename std::enable_if< Requires >::type + > + constexpr unique_resource_data() + noexcept(detail::conjunction< + std::is_nothrow_constructible< resource_holder, result_of_make_default >, + std::is_nothrow_default_constructible< deleter_holder > + >::value) : + resource_holder(traits_type::make_default()), + deleter_holder() + { + } + + unique_resource_data(unique_resource_data const&) = delete; + unique_resource_data& operator= (unique_resource_data const&) = delete; + + unique_resource_data(unique_resource_data&& that) + noexcept(detail::conjunction< + std::is_nothrow_constructible< internal_resource_type, typename detail::move_or_copy_construct_ref< resource_type >::type >, + std::is_nothrow_constructible< internal_deleter_type, typename detail::move_or_copy_construct_ref< deleter_type >::type > + >::value) : + unique_resource_data + ( + static_cast< unique_resource_data&& >(that), + typename std::is_nothrow_constructible< internal_resource_type, typename detail::move_or_copy_construct_ref< resource_type >::type >::type(), + typename std::is_nothrow_constructible< internal_deleter_type, typename detail::move_or_copy_construct_ref< deleter_type >::type >::type() + ) + { + } + + template< + typename D, + typename = typename std::enable_if< detail::conjunction< + std::is_constructible< resource_holder, result_of_make_default >, + std::is_constructible< deleter_holder, D > + >::value >::type + > + explicit unique_resource_data(default_resource_t, D&& del) + noexcept(detail::conjunction< + std::is_nothrow_constructible< resource_holder, result_of_make_default >, + std::is_nothrow_constructible< deleter_holder, D > + >::value) : + resource_holder(traits_type::make_default()), + deleter_holder(static_cast< D&& >(del)) + { + } + + template< + typename R, + typename D, + typename = typename std::enable_if< detail::conjunction< + detail::negation< detail::is_default_resource< R > >, + std::is_constructible< resource_holder, R, D, bool >, + std::is_constructible< deleter_holder, D, resource_type&, bool > + >::value >::type + > + explicit unique_resource_data(R&& res, D&& del) + noexcept(detail::conjunction< + std::is_nothrow_constructible< resource_holder, R, D, bool >, + std::is_nothrow_constructible< deleter_holder, D, resource_type&, bool > + >::value) : + unique_resource_data(static_cast< R&& >(res), static_cast< D&& >(del), traits_type::is_allocated(res)) // don't forward res to is_allocated to make sure res is not moved-from on resource construction + { + // Since res may not be of the resource type, the is_allocated call made above may require a type conversion or pick a different overload. + // We still require it to be noexcept, as we need to know whether we should deallocate it. Otherwise we may leak the resource. + static_assert(noexcept(traits_type::is_allocated(res)), "Invalid unique_resource resource traits: is_allocated must be noexcept"); + } + + template< + bool Requires = detail::conjunction< + std::is_assignable< internal_resource_type&, typename detail::move_or_copy_assign_ref< resource_type >::type >, + std::is_assignable< internal_deleter_type&, typename detail::move_or_copy_assign_ref< deleter_type >::type > + >::value + > + typename std::enable_if< Requires, unique_resource_data& >::type operator= (unique_resource_data&& that) + noexcept(detail::conjunction< + std::is_nothrow_assignable< internal_resource_type&, typename detail::move_or_copy_assign_ref< resource_type >::type >, + std::is_nothrow_assignable< internal_deleter_type&, typename detail::move_or_copy_assign_ref< deleter_type >::type > + >::value) + { + assign(static_cast< unique_resource_data&& >(that), typename std::is_nothrow_move_assignable< internal_deleter_type >::type()); + return *this; + } + + resource_type& get_resource() noexcept + { + return resource_holder::get(); + } + + resource_type const& get_resource() const noexcept + { + return resource_holder::get(); + } + + internal_resource_type& get_internal_resource() noexcept + { + return resource_holder::get_internal(); + } + + internal_resource_type const& get_internal_resource() const noexcept + { + return resource_holder::get_internal(); + } + + deleter_type& get_deleter() noexcept + { + return deleter_holder::get(); + } + + deleter_type const& get_deleter() const noexcept + { + return deleter_holder::get(); + } + + internal_deleter_type& get_internal_deleter() noexcept + { + return deleter_holder::get_internal(); + } + + internal_deleter_type const& get_internal_deleter() const noexcept + { + return deleter_holder::get_internal(); + } + + bool is_allocated() const noexcept + { + return traits_type::is_allocated(get_resource()); + } + + void set_unallocated() noexcept + { + get_internal_resource() = traits_type::make_default(); + } + + template< typename R > + void assign_resource(R&& res) noexcept(std::is_nothrow_assignable< internal_resource_type&, R >::value) + { + get_internal_resource() = static_cast< R&& >(res); + } + + template< + bool Requires = detail::conjunction< + detail::is_swappable< internal_resource_type >, + detail::is_swappable< internal_deleter_type >, + detail::disjunction< + detail::is_nothrow_swappable< internal_resource_type >, + detail::is_nothrow_swappable< internal_deleter_type > + > + >::value + > + typename std::enable_if< Requires >::type swap(unique_resource_data& that) + noexcept(detail::conjunction< detail::is_nothrow_swappable< internal_resource_type >, detail::is_nothrow_swappable< internal_deleter_type > >::value) + { + swap_impl + ( + that, + std::integral_constant< bool, detail::is_nothrow_swappable< internal_resource_type >::value >(), + std::integral_constant< bool, detail::conjunction< + detail::is_nothrow_swappable< internal_resource_type >, + detail::is_nothrow_swappable< internal_deleter_type > + >::value >() + ); + } + +private: + unique_resource_data(unique_resource_data&& that, std::true_type, std::true_type) noexcept : + resource_holder(static_cast< typename detail::move_or_copy_construct_ref< resource_type >::type >(that.get_resource())), + deleter_holder(static_cast< typename detail::move_or_copy_construct_ref< deleter_type >::type >(that.get_deleter())) + { + that.set_unallocated(); + } + + unique_resource_data(unique_resource_data&& that, std::false_type, std::true_type) : + resource_holder(static_cast< resource_type const& >(that.get_resource())), + deleter_holder(static_cast< typename detail::move_or_copy_construct_ref< deleter_type >::type >(that.get_deleter())) + { + that.set_unallocated(); + } + + unique_resource_data(unique_resource_data&& that, std::true_type, std::false_type) try : + resource_holder(static_cast< typename detail::move_or_copy_construct_ref< resource_type >::type >(that.get_resource())), + deleter_holder(static_cast< deleter_type const& >(that.get_deleter())) + { + that.set_unallocated(); + } + catch (...) + { + // Since only the deleter's constructor could have thrown an exception here, move the resource back + // to the original unique_resource. This is guaranteed to not throw. + that.resource_holder::move_from(static_cast< internal_resource_type&& >(resource_holder::get_internal())); + } + + unique_resource_data(unique_resource_data&& that, std::false_type, std::false_type) : + resource_holder(static_cast< resource_type const& >(that.get_resource())), + deleter_holder(static_cast< deleter_type const& >(that.get_deleter())) + { + that.set_unallocated(); + } + + template< + typename R, + typename D, + typename = typename std::enable_if< detail::conjunction< + std::is_constructible< resource_holder, R, D, bool >, + std::is_constructible< deleter_holder, D, resource_type&, bool > + >::value >::type + > + explicit unique_resource_data(R&& res, D&& del, bool allocated) + noexcept(detail::conjunction< + std::is_nothrow_constructible< resource_holder, R, D, bool >, + std::is_nothrow_constructible< deleter_holder, D, resource_type&, bool > + >::value) : + resource_holder(static_cast< R&& >(res), static_cast< D&& >(del), allocated), + deleter_holder(static_cast< D&& >(del), resource_holder::get(), allocated) + { + } + + void assign(unique_resource_data&& that, std::true_type) + noexcept(std::is_nothrow_assignable< internal_resource_type&, typename detail::move_or_copy_assign_ref< resource_type >::type >::value) + { + get_internal_resource() = static_cast< typename detail::move_or_copy_assign_ref< resource_type >::type >(that.get_resource()); + get_internal_deleter() = static_cast< typename detail::move_or_copy_assign_ref< deleter_type >::type >(that.get_deleter()); + + that.set_unallocated(); + } + + void assign(unique_resource_data&& that, std::false_type) + { + get_internal_deleter() = static_cast< typename detail::move_or_copy_assign_ref< deleter_type >::type >(that.get_deleter()); + get_internal_resource() = static_cast< typename detail::move_or_copy_assign_ref< resource_type >::type >(that.get_resource()); + + that.set_unallocated(); + } + + void swap_impl(unique_resource_data& that, std::true_type, std::true_type) noexcept + { + boost::core::invoke_swap(get_internal_resource(), that.get_internal_resource()); + boost::core::invoke_swap(get_internal_deleter(), that.get_internal_deleter()); + } + + void swap_impl(unique_resource_data& that, std::true_type, std::false_type) + { + boost::core::invoke_swap(get_internal_deleter(), that.get_internal_deleter()); + boost::core::invoke_swap(get_internal_resource(), that.get_internal_resource()); + } + + void swap_impl(unique_resource_data& that, std::false_type, std::false_type) + { + boost::core::invoke_swap(get_internal_resource(), that.get_internal_resource()); + boost::core::invoke_swap(get_internal_deleter(), that.get_internal_deleter()); + } +}; + +template< typename Resource, typename Deleter > +class unique_resource_data< Resource, Deleter, void > : + public detail::resource_holder< Resource, use_resource_compact_storage< Resource, Deleter >::value >, + public detail::deleter_holder< Resource, Deleter > +{ +public: + using resource_type = Resource; + using deleter_type = Deleter; + using traits_type = void; + +private: + using resource_holder = detail::resource_holder< resource_type, use_resource_compact_storage< resource_type, deleter_type >::value >; + using deleter_holder = detail::deleter_holder< resource_type, deleter_type >; + +public: + using internal_resource_type = typename resource_holder::internal_resource_type; + using internal_deleter_type = typename deleter_holder::internal_deleter_type; + +private: + bool m_allocated; + +public: + template< + bool Requires = detail::conjunction< std::is_default_constructible< resource_holder >, std::is_default_constructible< deleter_holder > >::value, + typename = typename std::enable_if< Requires >::type + > + constexpr unique_resource_data() + noexcept(detail::conjunction< std::is_nothrow_default_constructible< resource_holder >, std::is_nothrow_default_constructible< deleter_holder > >::value) : + resource_holder(), + deleter_holder(), + m_allocated(false) + { + } + + unique_resource_data(unique_resource_data const&) = delete; + unique_resource_data& operator= (unique_resource_data const&) = delete; + + template< + bool Requires = detail::conjunction< + std::is_constructible< internal_resource_type, typename detail::move_or_copy_construct_ref< resource_type >::type >, + std::is_constructible< internal_deleter_type, typename detail::move_or_copy_construct_ref< deleter_type >::type > + >::value, + typename = typename std::enable_if< Requires >::type + > + unique_resource_data(unique_resource_data&& that) + noexcept(detail::conjunction< + std::is_nothrow_constructible< internal_resource_type, typename detail::move_or_copy_construct_ref< resource_type >::type >, + std::is_nothrow_constructible< internal_deleter_type, typename detail::move_or_copy_construct_ref< deleter_type >::type > + >::value) : + unique_resource_data + ( + static_cast< unique_resource_data&& >(that), + typename std::is_nothrow_constructible< internal_resource_type, typename detail::move_or_copy_construct_ref< resource_type >::type >::type(), + typename std::is_nothrow_constructible< internal_deleter_type, typename detail::move_or_copy_construct_ref< deleter_type >::type >::type() + ) + { + } + + template< + typename D, + typename = typename std::enable_if< detail::conjunction< + std::is_default_constructible< resource_holder >, + std::is_constructible< deleter_holder, D > + >::value >::type + > + explicit unique_resource_data(default_resource_t, D&& del) + noexcept(detail::conjunction< + std::is_nothrow_default_constructible< resource_holder >, + std::is_nothrow_constructible< deleter_holder, D > + >::value) : + resource_holder(), + deleter_holder(static_cast< D&& >(del)), + m_allocated(false) + { + } + + template< + typename R, + typename D, + typename = typename std::enable_if< detail::conjunction< + detail::negation< detail::is_default_resource< R > >, + std::is_constructible< resource_holder, R, D, bool >, + std::is_constructible< deleter_holder, D, resource_type&, bool > + >::value >::type + > + explicit unique_resource_data(R&& res, D&& del) + noexcept(detail::conjunction< + std::is_nothrow_constructible< resource_holder, R, D, bool >, + std::is_nothrow_constructible< deleter_holder, D, resource_type&, bool > + >::value) : + resource_holder(static_cast< R&& >(res), static_cast< D&& >(del), true), + deleter_holder(static_cast< D&& >(del), resource_holder::get(), true), + m_allocated(true) + { + } + + template< + bool Requires = detail::conjunction< + std::is_assignable< internal_resource_type&, typename detail::move_or_copy_assign_ref< resource_type >::type >, + std::is_assignable< internal_deleter_type&, typename detail::move_or_copy_assign_ref< deleter_type >::type > + >::value + > + typename std::enable_if< Requires, unique_resource_data& >::type operator= (unique_resource_data&& that) + noexcept(detail::conjunction< + std::is_nothrow_assignable< internal_resource_type&, typename detail::move_or_copy_assign_ref< resource_type >::type >, + std::is_nothrow_assignable< internal_deleter_type&, typename detail::move_or_copy_assign_ref< deleter_type >::type > + >::value) + { + assign(static_cast< unique_resource_data&& >(that), typename std::is_nothrow_move_assignable< internal_deleter_type >::type()); + return *this; + } + + resource_type& get_resource() noexcept + { + return resource_holder::get(); + } + + resource_type const& get_resource() const noexcept + { + return resource_holder::get(); + } + + internal_resource_type& get_internal_resource() noexcept + { + return resource_holder::get_internal(); + } + + internal_resource_type const& get_internal_resource() const noexcept + { + return resource_holder::get_internal(); + } + + deleter_type& get_deleter() noexcept + { + return deleter_holder::get(); + } + + deleter_type const& get_deleter() const noexcept + { + return deleter_holder::get(); + } + + internal_deleter_type& get_internal_deleter() noexcept + { + return deleter_holder::get_internal(); + } + + internal_deleter_type const& get_internal_deleter() const noexcept + { + return deleter_holder::get_internal(); + } + + bool is_allocated() const noexcept + { + return m_allocated; + } + + void set_unallocated() noexcept + { + m_allocated = false; + } + + template< typename R > + void assign_resource(R&& res) noexcept(std::is_nothrow_assignable< internal_resource_type&, R >::value) + { + get_internal_resource() = static_cast< R&& >(res); + m_allocated = true; + } + + template< + bool Requires = detail::conjunction< + detail::is_swappable< internal_resource_type >, + detail::is_swappable< internal_deleter_type >, + detail::disjunction< + detail::is_nothrow_swappable< internal_resource_type >, + detail::is_nothrow_swappable< internal_deleter_type > + > + >::value + > + typename std::enable_if< Requires >::type swap(unique_resource_data& that) + noexcept(detail::conjunction< detail::is_nothrow_swappable< internal_resource_type >, detail::is_nothrow_swappable< internal_deleter_type > >::value) + { + swap_impl + ( + that, + std::integral_constant< bool, detail::is_nothrow_swappable< internal_resource_type >::value >(), + std::integral_constant< bool, detail::conjunction< + detail::is_nothrow_swappable< internal_resource_type >, + detail::is_nothrow_swappable< internal_deleter_type > + >::value >() + ); + } + +private: + unique_resource_data(unique_resource_data&& that, std::true_type, std::true_type) noexcept : + resource_holder(static_cast< typename detail::move_or_copy_construct_ref< resource_type >::type >(that.get_resource())), + deleter_holder(static_cast< typename detail::move_or_copy_construct_ref< deleter_type >::type >(that.get_deleter())), + m_allocated(that.m_allocated) + { + that.m_allocated = false; + } + + unique_resource_data(unique_resource_data&& that, std::false_type, std::true_type) : + resource_holder(static_cast< resource_type const& >(that.get_resource())), + deleter_holder(static_cast< typename detail::move_or_copy_construct_ref< deleter_type >::type >(that.get_deleter())), + m_allocated(that.m_allocated) + { + that.m_allocated = false; + } + + unique_resource_data(unique_resource_data&& that, std::true_type, std::false_type) try : + resource_holder(static_cast< typename detail::move_or_copy_construct_ref< resource_type >::type >(that.get_resource())), + deleter_holder(static_cast< deleter_type const& >(that.get_deleter())), + m_allocated(that.m_allocated) + { + that.m_allocated = false; + } + catch (...) + { + // Since only the deleter's constructor could have thrown an exception here, move the resource back + // to the original unique_resource. This is guaranteed to not throw. + that.resource_holder::move_from(static_cast< internal_resource_type&& >(resource_holder::get_internal())); + } + + unique_resource_data(unique_resource_data&& that, std::false_type, std::false_type) : + resource_holder(static_cast< resource_type const& >(that.get_resource())), + deleter_holder(static_cast< deleter_type const& >(that.get_deleter())), + m_allocated(that.m_allocated) + { + that.m_allocated = false; + } + + void assign(unique_resource_data&& that, std::true_type) + noexcept(std::is_nothrow_assignable< internal_resource_type&, typename detail::move_or_copy_assign_ref< resource_type >::type >::value) + { + get_internal_resource() = static_cast< typename detail::move_or_copy_assign_ref< resource_type >::type >(that.get_resource()); + get_internal_deleter() = static_cast< typename detail::move_or_copy_assign_ref< deleter_type >::type >(that.get_deleter()); + + m_allocated = that.m_allocated; + that.m_allocated = false; + } + + void assign(unique_resource_data&& that, std::false_type) + { + get_internal_deleter() = static_cast< typename detail::move_or_copy_assign_ref< deleter_type >::type >(that.get_deleter()); + get_internal_resource() = static_cast< typename detail::move_or_copy_assign_ref< resource_type >::type >(that.get_resource()); + + m_allocated = that.m_allocated; + that.m_allocated = false; + } + + void swap_impl(unique_resource_data& that, std::true_type, std::true_type) noexcept + { + boost::core::invoke_swap(get_internal_resource(), that.get_internal_resource()); + boost::core::invoke_swap(get_internal_deleter(), that.get_internal_deleter()); + boost::core::invoke_swap(m_allocated, that.m_allocated); + } + + void swap_impl(unique_resource_data& that, std::true_type, std::false_type) + { + boost::core::invoke_swap(get_internal_deleter(), that.get_internal_deleter()); + boost::core::invoke_swap(get_internal_resource(), that.get_internal_resource()); + boost::core::invoke_swap(m_allocated, that.m_allocated); + } + + void swap_impl(unique_resource_data& that, std::false_type, std::false_type) + { + boost::core::invoke_swap(get_internal_resource(), that.get_internal_resource()); + boost::core::invoke_swap(get_internal_deleter(), that.get_internal_deleter()); + boost::core::invoke_swap(m_allocated, that.m_allocated); + } +}; + +template< typename T > +struct is_dereferenceable_impl +{ + template< typename U, typename R = decltype(*std::declval< U const& >()) > + static std::true_type _is_dereferenceable_check(int); + template< typename U > + static std::false_type _is_dereferenceable_check(...); + + using type = decltype(is_dereferenceable_impl::_is_dereferenceable_check< T >(0)); +}; + +template< typename T > +struct is_dereferenceable : public is_dereferenceable_impl< T >::type { }; +template< > +struct is_dereferenceable< void* > : public std::false_type { }; +template< > +struct is_dereferenceable< const void* > : public std::false_type { }; +template< > +struct is_dereferenceable< volatile void* > : public std::false_type { }; +template< > +struct is_dereferenceable< const volatile void* > : public std::false_type { }; +template< > +struct is_dereferenceable< void*& > : public std::false_type { }; +template< > +struct is_dereferenceable< const void*& > : public std::false_type { }; +template< > +struct is_dereferenceable< volatile void*& > : public std::false_type { }; +template< > +struct is_dereferenceable< const volatile void*& > : public std::false_type { }; +template< > +struct is_dereferenceable< void* const& > : public std::false_type { }; +template< > +struct is_dereferenceable< const void* const& > : public std::false_type { }; +template< > +struct is_dereferenceable< volatile void* const& > : public std::false_type { }; +template< > +struct is_dereferenceable< const volatile void* const& > : public std::false_type { }; +template< > +struct is_dereferenceable< void* volatile& > : public std::false_type { }; +template< > +struct is_dereferenceable< const void* volatile& > : public std::false_type { }; +template< > +struct is_dereferenceable< volatile void* volatile& > : public std::false_type { }; +template< > +struct is_dereferenceable< const volatile void* volatile& > : public std::false_type { }; +template< > +struct is_dereferenceable< void* const volatile& > : public std::false_type { }; +template< > +struct is_dereferenceable< const void* const volatile& > : public std::false_type { }; +template< > +struct is_dereferenceable< volatile void* const volatile& > : public std::false_type { }; +template< > +struct is_dereferenceable< const volatile void* const volatile& > : public std::false_type { }; + +template< typename T, bool = detail::is_dereferenceable< T >::value > +struct dereference_traits { }; +template< typename T > +struct dereference_traits< T, true > +{ + using result_type = decltype(*std::declval< T const& >()); + static constexpr bool is_noexcept = noexcept(*std::declval< T const& >()); +}; + +} // namespace detail + +/*! + * \brief RAII wrapper for automatically reclaiming arbitrary resources. + * + * A \c unique_resource object exclusively owns wrapped resource and invokes + * the deleter function object on it on destruction. The wrapped resource can have + * any type that is: + * + * \li Move-constructible, where the move constructor is marked as `noexcept`, or + * \li Copy-constructible, or + * \li An lvalue reference to an object type. + * + * The deleter must be a function object type that is callable on an lvalue + * of the resource type. The deleter must be copy-constructible. + * + * An optional resource traits template parameter may be specified. Resource + * traits can be used to optimize \c unique_resource implementation when + * the following conditions are met: + * + * \li There is at least one value of the resource type that is considered + * unallocated (that is, no allocated resource shall be equal to one of + * the unallocated resource values). The unallocated resource values need not + * be deallocated using the deleter. + * \li One of the unallocated resource values can be considered the default. + * Constructing the default resource value and assigning it to a resource + * object (whether allocated or not) shall not throw exceptions. + * \li Resource objects can be tested for being unallocated. Such a test shall + * not throw exceptions. + * + * If specified, the resource traits must be a class type that has the following + * public static members: + * + * \li `R make_default() noexcept` - must return the default resource value such + * that `std::is_constructible< Resource, R >::value && + * std::is_nothrow_assignable< Resource&, R >::value` is \c true. + * \li `bool is_allocated(Resource const& res) noexcept` - must return \c true + * if \c res is not one of the unallocated resource values and \c false + * otherwise. + * + * Note that `is_allocated(make_default())` must always return \c false. + * + * When resource traits satisfying the above requirements are specified, + * \c unique_resource will be able to avoid storing additional indication of + * whether the owned resource object needs to be deallocated with the deleter + * on destruction. It will use the default resource value to initialize the owned + * resource object when \c unique_resource is not in the allocated state. + * Additionally, it will be possible to construct \c unique_resource with + * unallocated resource values, which will create \c unique_resource objects in + * unallocated state (the deleter will not be called on unallocated resource + * values). + * + * \tparam Resource Resource type. + * \tparam Deleter Resource deleter function object type. + * \tparam Traits Optional resource traits type. + */ +template< typename Resource, typename Deleter, typename Traits BOOST_SCOPE_DETAIL_DOC(= void) > +class unique_resource +{ +public: + //! Resource type + using resource_type = Resource; + //! Deleter type + using deleter_type = Deleter; + //! Resource traits + using traits_type = Traits; + +//! \cond +private: + using data = detail::unique_resource_data< resource_type, deleter_type, traits_type >; + using internal_resource_type = typename data::internal_resource_type; + using internal_deleter_type = typename data::internal_deleter_type; + + data m_data; + +//! \endcond +public: + /*! + * \brief Constructs an unallocated unique resource guard. + * + * **Requires:** Default \c Resource value can be constructed. \c Deleter is default-constructible + * and is not a pointer to function. + * + * **Effects:** Initializes the \c Resource object with the default resource value. Default-constructs + * the \c Deleter object. + * + * **Throws:** Nothing, unless construction of \c Resource or \c Deleter throws. + * + * \post `this->allocated() == false` + */ + //! \cond + template< + bool Requires = std::is_default_constructible< data >::value, + typename = typename std::enable_if< Requires >::type + > + //! \endcond + constexpr unique_resource() noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(std::is_nothrow_default_constructible< data >::value)) + { + } + + /*! + * \brief Constructs an unallocated unique resource guard with the given deleter. + * + * **Requires:** Default \c Resource value can be constructed and \c Deleter is constructible from \a del. + * + * **Effects:** Initializes the \c Resource value with the default resource value. If \c Deleter is nothrow + * constructible from `D&&` then constructs \c Deleter from `std::forward< D >(del)`, + * otherwise constructs from `del`. + * + * **Throws:** Nothing, unless construction of \c Resource or \c Deleter throws. + * + * \param res A tag argument indicating default resource value. + * \param del Resource deleter function object. + * + * \post `this->allocated() == false` + */ + template< + typename D + //! \cond + , typename = typename std::enable_if< + std::is_constructible< data, default_resource_t, typename detail::move_or_copy_construct_ref< D, deleter_type >::type >::value + >::type + //! \endcond + > + unique_resource(default_resource_t res, D&& del) + noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN( + std::is_nothrow_constructible< + data, + default_resource_t, + typename detail::move_or_copy_construct_ref< D, deleter_type >::type + >::value + )) : + m_data + ( + res, + static_cast< typename detail::move_or_copy_construct_ref< D, deleter_type >::type >(del) + ) + { + } + + /*! + * \brief Constructs a unique resource guard with the given resource and a default-constructed deleter. + * + * **Requires:** \c Resource is constructible from \a res. \c Deleter is default-constructible and + * is not a pointer to function. + * + * **Effects:** Constructs the unique resource object as if by calling + * `unique_resource(std::forward< R >(res), Deleter())`. + * + * **Throws:** Nothing, unless construction of \c Resource or \c Deleter throws. + * + * \param res Resource object. + */ + template< + typename R + //! \cond + , typename = typename std::enable_if< detail::conjunction< + detail::is_nothrow_nonnull_default_constructible< deleter_type >, + std::is_constructible< data, typename detail::move_or_copy_construct_ref< R, resource_type >::type, typename detail::move_or_copy_construct_ref< deleter_type >::type >, + detail::disjunction< detail::negation< std::is_reference< resource_type > >, std::is_reference< R > > // prevent binding lvalue-reference resource to an rvalue + >::value >::type + //! \endcond + > + explicit unique_resource(R&& res) + noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN( + std::is_nothrow_constructible< + data, + typename detail::move_or_copy_construct_ref< R, resource_type >::type, + typename detail::move_or_copy_construct_ref< deleter_type >::type + >::value + )) : + m_data + ( + static_cast< typename detail::move_or_copy_construct_ref< R, resource_type >::type >(res), + static_cast< typename detail::move_or_copy_construct_ref< deleter_type >::type >(deleter_type()) + ) + { + } + + /*! + * \brief Constructs a unique resource guard with the given resource and deleter. + * + * **Requires:** \c Resource is constructible from \a res and \c Deleter is constructible from \a del. + * + * **Effects:** If \c Resource is nothrow constructible from `R&&` then constructs \c Resource + * from `std::forward< R >(res)`, otherwise constructs from `res`. If \c Deleter + * is nothrow constructible from `D&&` then constructs \c Deleter from + * `std::forward< D >(del)`, otherwise constructs from `del`. + * + * If construction of \c Resource or \c Deleter throws and \a res is not an unallocated resource + * value, invokes \a del on \a res (if \c Resource construction failed) or the constructed + * \c Resource object (if \c Deleter construction failed). + * + * **Throws:** Nothing, unless construction of \c Resource or \c Deleter throws. + * + * \param res Resource object. + * \param del Resource deleter function object. + * + * \post If \a res is an unallocated resource value then `this->allocated() == false`, otherwise + * `this->allocated() == true`. + */ + template< + typename R, + typename D + //! \cond + , typename = typename std::enable_if< detail::conjunction< + std::is_constructible< data, typename detail::move_or_copy_construct_ref< R, resource_type >::type, typename detail::move_or_copy_construct_ref< D, deleter_type >::type >, + detail::disjunction< detail::negation< std::is_reference< resource_type > >, std::is_reference< R > > // prevent binding lvalue-reference resource to an rvalue + >::value >::type + //! \endcond + > + unique_resource(R&& res, D&& del) + noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN( + std::is_nothrow_constructible< + data, + typename detail::move_or_copy_construct_ref< R, resource_type >::type, + typename detail::move_or_copy_construct_ref< D, deleter_type >::type + >::value + )) : + m_data + ( + static_cast< typename detail::move_or_copy_construct_ref< R, resource_type >::type >(res), + static_cast< typename detail::move_or_copy_construct_ref< D, deleter_type >::type >(del) + ) + { + } + + unique_resource(unique_resource const&) = delete; + unique_resource& operator= (unique_resource const&) = delete; + + /*! + * \brief Move-constructs a unique resource guard. + * + * **Requires:** \c Resource and \c Deleter are move-constructible. + * + * **Effects:** If \c Resource is nothrow move-constructible then move-constructs \c Resource, + * otherwise copy-constructs. If \c Deleter is nothrow move-constructible then move-constructs + * \c Deleter, otherwise copy-constructs. Deactivates the moved-from unique resource object. + * + * If an exception is thrown during construction, \a that is left in its original state. + * + * \note This logic ensures that in case of exception the resource is not leaked and remains owned by the + * move source. + * + * **Throws:** Nothing, unless construction of \c Resource or \c Deleter throws. + * + * \param that Move source. + * + * \post Let \c allocated be equal to `that.allocated()` prior to the operation. Then + * `this->allocated() == allocated` and `that.allocated() == false`. + */ + //! \cond + template< + bool Requires = std::is_move_constructible< data >::value, + typename = typename std::enable_if< Requires >::type + > + //! \endcond + unique_resource(unique_resource&& that) noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(std::is_nothrow_move_constructible< data >::value)) : + m_data(static_cast< data&& >(that.m_data)) + { + } + + /*! + * \brief Move-assigns a unique resource guard. + * + * **Requires:** \c Resource and \c Deleter are move-assignable. + * + * **Effects:** Calls `this->reset()`. Then, if \c Deleter is nothrow move-assignable, move-assigns + * the \c Deleter object first and the \c Resource object next. Otherwise, move-assigns + * the objects in reverse order. Lastly, deactivates the moved-from unique resource object. + * + * If an exception is thrown, \a that is left in its original state. + * + * \note The different orders of assignment ensure that in case of exception the resource is not leaked + * and remains owned by the move source. + * + * **Throws:** Nothing, unless assignment of \c Resource or \c Deleter throws. + * + * \param that Move source. + * + * \post Let \c allocated be equal to `that.allocated()` prior to the operation. Then + * `this->allocated() == allocated` and `that.allocated() == false`. + */ +#if !defined(BOOST_SCOPE_DOXYGEN) + template< bool Requires = std::is_move_assignable< data >::value > + typename std::enable_if< Requires, unique_resource& >::type +#else + unique_resource& +#endif + operator= (unique_resource&& that) + noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(std::is_nothrow_move_assignable< data >::value)) + { + reset(); + m_data = static_cast< data&& >(that.m_data); + return *this; + } + + /*! + * \brief If the resource is allocated, calls the deleter function on it. Destroys the resource and the deleter. + * + * **Throws:** Nothing, unless invoking the deleter throws. + */ + ~unique_resource() noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(detail::is_nothrow_invocable< deleter_type&, resource_type& >::value)) + { + if (BOOST_LIKELY(m_data.is_allocated())) + m_data.get_deleter()(m_data.get_resource()); + } + + /*! + * \brief Returns \c true if the resource is allocated and to be reclaimed by the deleter, otherwise \c false. + * + * \note This method does not test the value of the resource. + * + * **Throws:** Nothing. + */ + explicit operator bool () const noexcept + { + return m_data.is_allocated(); + } + + /*! + * \brief Returns \c true if the resource is allocated and to be reclaimed by the deleter, otherwise \c false. + * + * **Throws:** Nothing. + */ + bool allocated() const noexcept + { + return m_data.is_allocated(); + } + + /*! + * \brief Returns a reference to the resource object. + * + * **Throws:** Nothing. + */ + resource_type const& get() const noexcept + { + return m_data.get_resource(); + } + + /*! + * \brief Returns a reference to the deleter object. + * + * **Throws:** Nothing. + */ + deleter_type const& get_deleter() const noexcept + { + return m_data.get_deleter(); + } + + /*! + * \brief Marks the resource as unallocated. Does not call the deleter if the resource was previously allocated. + * + * **Throws:** Nothing. + * + * \post `this->allocated() == false` + */ + void release() noexcept + { + m_data.set_unallocated(); + } + + /*! + * \brief If the resource is allocated, calls the deleter function on it and marks the resource as unallocated. + * + * **Throws:** Nothing, unless invoking the deleter throws. + * + * \post `this->allocated() == false` + */ + void reset() noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(detail::is_nothrow_invocable< deleter_type&, resource_type& >::value)) + { + if (BOOST_LIKELY(m_data.is_allocated())) + { + m_data.get_deleter()(m_data.get_resource()); + m_data.set_unallocated(); + } + } + + /*! + * \brief Assigns a new resource object to the unique resource wrapper. + * + * **Effects:** Calls `this->reset()`. Then, if \c Resource is nothrow assignable from `R&&`, + * assigns `std::forward< R >(res)` to the stored resource object, otherwise assigns + * `res`. + * + * If \a res is not an unallocated resource value and an exception is thrown during the operation, + * invokes the stored deleter on \a res before returning with the exception. + * + * **Throws:** Nothing, unless invoking the deleter throws. + * + * \param res Resource object to assign. + * + * \post `this->allocated() == false` + */ + template< typename R > +#if !defined(BOOST_SCOPE_DOXYGEN) + typename std::enable_if< detail::conjunction< + std::is_assignable< internal_resource_type&, typename detail::move_or_copy_assign_ref< R, resource_type >::type >, + detail::disjunction< detail::negation< std::is_reference< resource_type > >, std::is_reference< R > > // prevent binding lvalue-reference resource to an rvalue + >::value >::type +#else + void +#endif + reset(R&& res) + noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN( + detail::conjunction< + detail::is_nothrow_invocable< deleter_type&, resource_type& >, + std::is_nothrow_assignable< internal_resource_type&, typename detail::move_or_copy_assign_ref< R, resource_type >::type > + >::value + )) + { + reset_impl + ( + static_cast< R&& >(res), + typename detail::conjunction< + detail::is_nothrow_invocable< deleter_type&, resource_type& >, + std::is_nothrow_assignable< internal_resource_type&, typename detail::move_or_copy_assign_ref< R, resource_type >::type > + >::type() + ); + } + + /*! + * \brief Invokes indirection on the resource object. + * + * **Requires:** \c Resource is dereferenceable. + * + * **Effects:** Returns a reference to the resource object as if by calling `get()`. + * + * \note If \c Resource is not a pointer type, the compiler will invoke its `operator->`. + * Such call sequence will continue until a pointer is obtained. + * + * **Throws:** Nothing. Note that any implicit subsequent calls to other `operator->` + * functions that are caused by this call may have different throw conditions. + */ +#if !defined(BOOST_SCOPE_DOXYGEN) + template< bool Requires = detail::is_dereferenceable< resource_type >::value > + typename std::enable_if< Requires, resource_type const& >::type +#else + resource_type const& +#endif + operator-> () const noexcept + { + return get(); + } + + /*! + * \brief Dereferences the resource object. + * + * **Requires:** \c Resource is dereferenceable. + * + * **Effects:** Returns the result of dereferencing the resource object as if by calling `*get()`. + * + * **Throws:** Nothing, unless dereferencing the resource object throws. + */ +#if !defined(BOOST_SCOPE_DOXYGEN) + template< bool Requires = detail::is_dereferenceable< resource_type >::value > + typename detail::dereference_traits< resource_type, Requires >::result_type +#else + auto +#endif + operator* () const + noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(detail::dereference_traits< resource_type, Requires >::is_noexcept)) + { + return *get(); + } + + /*! + * \brief Swaps two unique resource wrappers. + * + * **Requires:** \c Resource and \c Deleter are swappable. At least one of \c Resource and \c Deleter + * is nothrow swappable. + * + * **Effects:** Swaps the resource objects and deleter objects stored in `*this` and \a that + * as if by calling unqualified `swap` in a context where `std::swap` is + * found by overload resolution. + * + * If an exception is thrown, and the failed swap operation supports strong exception + * guarantee, both `*this` and \a that are left in their original states. + * + * **Throws:** Nothing, unless swapping the resource objects or deleters throw. + * + * \param that Unique resource wrapper to swap with. + */ +#if !defined(BOOST_SCOPE_DOXYGEN) + template< bool Requires = detail::is_swappable< data >::value > + typename std::enable_if< Requires >::type +#else + void +#endif + swap(unique_resource& that) + noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(detail::is_nothrow_swappable< data >::value)) + { + m_data.swap(that.m_data); + } + + /*! + * \brief Swaps two unique resource wrappers. + * + * **Effects:** As if `left.swap(right)`. + */ +#if !defined(BOOST_SCOPE_DOXYGEN) + template< bool Requires = detail::is_swappable< data >::value > + friend typename std::enable_if< Requires >::type +#else + friend void +#endif + swap(unique_resource& left, unique_resource& right) + noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(detail::is_nothrow_swappable< data >::value)) + { + left.swap(right); + } + +//! \cond +private: + //! Assigns a new resource object to the unique resource wrapper. + template< typename R > + void reset_impl(R&& res, std::true_type) noexcept + { + reset(); + m_data.assign_resource(static_cast< typename detail::move_or_copy_assign_ref< R, resource_type >::type >(res)); + } + + //! Assigns a new resource object to the unique resource wrapper. + template< typename R > + void reset_impl(R&& res, std::false_type) + { + try + { + reset(); + m_data.assign_resource(static_cast< typename detail::move_or_copy_assign_ref< R, resource_type >::type >(res)); + } + catch (...) + { + m_data.get_deleter()(static_cast< R&& >(res)); + throw; + } + } +//! \endcond +}; + +#if !defined(BOOST_NO_CXX17_DEDUCTION_GUIDES) +template< + typename Resource, + typename Deleter, + typename = typename std::enable_if< !detail::is_default_resource< Resource >::value >::type +> +unique_resource(Resource, Deleter) -> unique_resource< Resource, Deleter >; +#endif // !defined(BOOST_NO_CXX17_DEDUCTION_GUIDES) + +/*! + * \brief Checks if the resource is valid and creates a \c unique_resource wrapper. + * + * **Effects:** If the resource \a res is not equal to \a invalid, creates a unique resource wrapper + * that is in allocated state and owns \a res. Otherwise creates a unique resource wrapper + * in unallocated state. + * + * \note This function does not call \a del if \a res is equal to \a invalid. + * + * **Throws:** Nothing, unless \c unique_resource constructor throws. + * + * \param res Resource to wrap. + * \param invalid An invalid value for the resource. + * \param del A deleter to invoke on the resource to free it. + */ +template< typename Resource, typename Deleter, typename Invalid > +inline 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 + )) +{ + using unique_resource_type = unique_resource< typename std::decay< Resource >::type, typename std::decay< Deleter >::type >; + if (!(res == invalid)) + return unique_resource_type(static_cast< Resource&& >(res), static_cast< Deleter&& >(del)); + else + return unique_resource_type(default_resource_t(), static_cast< Deleter&& >(del)); +} + +} // namespace scope +} // namespace boost + +#include <boost/scope/detail/footer.hpp> + +#endif // BOOST_SCOPE_UNIQUE_RESOURCE_HPP_INCLUDED_ diff --git a/contrib/restricted/boost/scope/include/boost/scope/unique_resource_fwd.hpp b/contrib/restricted/boost/scope/include/boost/scope/unique_resource_fwd.hpp new file mode 100644 index 0000000000..aa9c30ec92 --- /dev/null +++ b/contrib/restricted/boost/scope/include/boost/scope/unique_resource_fwd.hpp @@ -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_ diff --git a/contrib/restricted/boost/scope/ya.make b/contrib/restricted/boost/scope/ya.make new file mode 100644 index 0000000000..b81b5900fe --- /dev/null +++ b/contrib/restricted/boost/scope/ya.make @@ -0,0 +1,27 @@ +# Generated by devtools/yamaker from nixpkgs 22.11. + +LIBRARY() + +LICENSE(BSL-1.0) + +LICENSE_TEXTS(.yandex_meta/licenses.list.txt) + +VERSION(1.86.0) + +ORIGINAL_SOURCE(https://github.com/boostorg/scope/archive/boost-1.86.0.tar.gz) + +PEERDIR( + contrib/restricted/boost/config + contrib/restricted/boost/core + contrib/restricted/boost/type_traits +) + +ADDINCL( + GLOBAL contrib/restricted/boost/scope/include +) + +NO_COMPILER_WARNINGS() + +NO_UTIL() + +END() |