gnss-sim/3rdparty/boost/scope/defer.hpp

181 lines
5.3 KiB
C++

/*
* 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_