mirror of
https://github.com/BlackMATov/meta.hpp.git
synced 2025-12-13 11:17:06 +07:00
add embedded defer.hpp
This commit is contained in:
@@ -9,6 +9,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <cassert>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
#include <compare>
|
#include <compare>
|
||||||
#include <concepts>
|
#include <concepts>
|
||||||
@@ -17,6 +18,7 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
#include <exception>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
#include <map>
|
#include <map>
|
||||||
@@ -28,6 +30,8 @@
|
|||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
#include <typeindex>
|
||||||
|
#include <typeinfo>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <version>
|
#include <version>
|
||||||
@@ -40,24 +44,19 @@
|
|||||||
# define META_HPP_NO_RTTI
|
# define META_HPP_NO_RTTI
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(META_HPP_NO_EXCEPTIONS)
|
|
||||||
# include <exception>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(META_HPP_NO_RTTI)
|
|
||||||
# include <typeindex>
|
|
||||||
# include <typeinfo>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(META_HPP_FWD)
|
#if !defined(META_HPP_FWD)
|
||||||
# define META_HPP_FWD(v) std::forward<decltype(v)>(v)
|
# define META_HPP_FWD(v) std::forward<decltype(v)>(v)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(META_HPP_ASSERT)
|
#if !defined(META_HPP_ASSERT)
|
||||||
# include <cassert>
|
|
||||||
# define META_HPP_ASSERT(...) assert(__VA_ARGS__) // NOLINT
|
# define META_HPP_ASSERT(...) assert(__VA_ARGS__) // NOLINT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !defined(META_HPP_PP_CAT)
|
||||||
|
# define META_HPP_PP_CAT(x, y) META_HPP_PP_CAT_I(x, y)
|
||||||
|
# define META_HPP_PP_CAT_I(x, y) x##y
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace meta_hpp::detail
|
namespace meta_hpp::detail
|
||||||
{
|
{
|
||||||
template < typename Enum >
|
template < typename Enum >
|
||||||
@@ -303,6 +302,141 @@ namespace meta_hpp::detail
|
|||||||
using copy_cvref_t = typename copy_cvref<From, To>::type;
|
using copy_cvref_t = typename copy_cvref<From, To>::type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace meta_hpp::detail::impl
|
||||||
|
{
|
||||||
|
template < typename F, typename... Args >
|
||||||
|
class defer_impl {
|
||||||
|
public:
|
||||||
|
defer_impl() = delete;
|
||||||
|
defer_impl(defer_impl&&) = delete;
|
||||||
|
defer_impl(const defer_impl&) = delete;
|
||||||
|
defer_impl& operator=(defer_impl&&) = delete;
|
||||||
|
defer_impl& operator=(const defer_impl&) = delete;
|
||||||
|
|
||||||
|
template < typename UF >
|
||||||
|
explicit defer_impl(UF&& f, std::tuple<Args...>&& args)
|
||||||
|
: f_{std::forward<UF>(f)}
|
||||||
|
, args_{std::move(args)} {}
|
||||||
|
|
||||||
|
void dismiss() noexcept {
|
||||||
|
dismissed_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
~defer_impl() noexcept {
|
||||||
|
if ( !dismissed_ ) {
|
||||||
|
std::apply(std::move(f_), std::move(args_));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
F f_;
|
||||||
|
std::tuple<Args...> args_;
|
||||||
|
bool dismissed_{};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace meta_hpp::detail
|
||||||
|
{
|
||||||
|
template < typename F, typename... Args >
|
||||||
|
class defer final : public impl::defer_impl<F, Args...> {
|
||||||
|
public:
|
||||||
|
defer() = delete;
|
||||||
|
defer(defer&&) = delete;
|
||||||
|
defer(const defer&) = delete;
|
||||||
|
defer& operator=(defer&&) = delete;
|
||||||
|
defer& operator=(const defer&) = delete;
|
||||||
|
|
||||||
|
template < typename UF >
|
||||||
|
explicit defer(UF&& f, std::tuple<Args...>&& args)
|
||||||
|
: impl::defer_impl<F, Args...>{std::forward<UF>(f), std::move(args)} {}
|
||||||
|
|
||||||
|
~defer() noexcept = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
template < typename F, typename... Args >
|
||||||
|
class error_defer final : public impl::defer_impl<F, Args...> {
|
||||||
|
public:
|
||||||
|
error_defer() = delete;
|
||||||
|
error_defer(error_defer&&) = delete;
|
||||||
|
error_defer(const error_defer&) = delete;
|
||||||
|
error_defer& operator=(error_defer&&) = delete;
|
||||||
|
error_defer& operator=(const error_defer&) = delete;
|
||||||
|
|
||||||
|
template < typename UF >
|
||||||
|
explicit error_defer(UF&& f, std::tuple<Args...>&& args)
|
||||||
|
: impl::defer_impl<F, Args...>{std::forward<UF>(f), std::move(args)}
|
||||||
|
, exceptions_{std::uncaught_exceptions()} {}
|
||||||
|
|
||||||
|
~error_defer() noexcept {
|
||||||
|
if ( exceptions_ == std::uncaught_exceptions() ) {
|
||||||
|
this->dismiss();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int exceptions_{};
|
||||||
|
};
|
||||||
|
|
||||||
|
template < typename F, typename... Args >
|
||||||
|
class return_defer final : public impl::defer_impl<F, Args...> {
|
||||||
|
public:
|
||||||
|
return_defer() = delete;
|
||||||
|
return_defer(return_defer&&) = delete;
|
||||||
|
return_defer(const return_defer&) = delete;
|
||||||
|
return_defer& operator=(return_defer&&) = delete;
|
||||||
|
return_defer& operator=(const return_defer&) = delete;
|
||||||
|
|
||||||
|
template < typename UF >
|
||||||
|
explicit return_defer(UF&& f, std::tuple<Args...>&& args)
|
||||||
|
: impl::defer_impl<F, Args...>{std::forward<UF>(f), std::move(args)}
|
||||||
|
, exceptions_{std::uncaught_exceptions()} {}
|
||||||
|
|
||||||
|
~return_defer() noexcept {
|
||||||
|
if ( exceptions_ != std::uncaught_exceptions() ) {
|
||||||
|
this->dismiss();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int exceptions_{};
|
||||||
|
};
|
||||||
|
|
||||||
|
template < typename F, typename... Args >
|
||||||
|
auto make_defer(F&& f, Args&&... args) {
|
||||||
|
using defer_t = defer<std::decay_t<F>, std::decay_t<Args>...>;
|
||||||
|
return defer_t{std::forward<F>(f), std::make_tuple(std::forward<Args>(args)...)};
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename F, typename... Args >
|
||||||
|
auto make_error_defer(F&& f, Args&&... args) {
|
||||||
|
using defer_t = error_defer<std::decay_t<F>, std::decay_t<Args>...>;
|
||||||
|
return defer_t{std::forward<F>(f), std::make_tuple(std::forward<Args>(args)...)};
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename F, typename... Args >
|
||||||
|
auto make_return_defer(F&& f, Args&&... args) {
|
||||||
|
using defer_t = return_defer<std::decay_t<F>, std::decay_t<Args>...>;
|
||||||
|
return defer_t{std::forward<F>(f), std::make_tuple(std::forward<Args>(args)...)};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __COUNTER__
|
||||||
|
# define META_HPP_DEFER(...) \
|
||||||
|
auto META_HPP_PP_CAT(meta_hpp_generated_defer_, __COUNTER__) { ::meta_hpp::detail::make_defer(__VA_ARGS__) }
|
||||||
|
# define META_HPP_ERROR_DEFER(...) \
|
||||||
|
auto META_HPP_PP_CAT(meta_hpp_generated_error_defer_, __COUNTER__) { ::meta_hpp::detail::make_error_defer(__VA_ARGS__) }
|
||||||
|
# define META_HPP_RETURN_DEFER(...) \
|
||||||
|
auto META_HPP_PP_CAT(meta_hpp_generated_return_defer_, __COUNTER__) { ::meta_hpp::detail::make_return_defer(__VA_ARGS__) }
|
||||||
|
#else
|
||||||
|
# define META_HPP_DEFER(...) \
|
||||||
|
auto META_HPP_PP_CAT(meta_hpp_generated_defer_, __LINE__) { ::meta_hpp::detail::make_defer(__VA_ARGS__) }
|
||||||
|
# define META_HPP_ERROR_DEFER(...) \
|
||||||
|
auto META_HPP_PP_CAT(meta_hpp_generated_error_defer_, __LINE__) { ::meta_hpp::detail::make_error_defer(__VA_ARGS__) }
|
||||||
|
# define META_HPP_RETURN_DEFER(...) \
|
||||||
|
auto META_HPP_PP_CAT(meta_hpp_generated_return_defer_, __LINE__) { ::meta_hpp::detail::make_return_defer(__VA_ARGS__) }
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !defined(META_HPP_NO_EXCEPTIONS)
|
#if !defined(META_HPP_NO_EXCEPTIONS)
|
||||||
# define META_HPP_TRY try
|
# define META_HPP_TRY try
|
||||||
# define META_HPP_CATCH(...) catch ( __VA_ARGS__ )
|
# define META_HPP_CATCH(...) catch ( __VA_ARGS__ )
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include "meta_base/bitflags.hpp"
|
#include "meta_base/bitflags.hpp"
|
||||||
#include "meta_base/cv_traits.hpp"
|
#include "meta_base/cv_traits.hpp"
|
||||||
#include "meta_base/cvref_traits.hpp"
|
#include "meta_base/cvref_traits.hpp"
|
||||||
|
#include "meta_base/defer.hpp"
|
||||||
#include "meta_base/exceptions.hpp"
|
#include "meta_base/exceptions.hpp"
|
||||||
#include "meta_base/fixed_function.hpp"
|
#include "meta_base/fixed_function.hpp"
|
||||||
#include "meta_base/fnv1a_hash.hpp"
|
#include "meta_base/fnv1a_hash.hpp"
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
@@ -18,6 +19,7 @@
|
|||||||
#include <compare>
|
#include <compare>
|
||||||
#include <concepts>
|
#include <concepts>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
#include <exception>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
#include <map>
|
#include <map>
|
||||||
@@ -29,6 +31,8 @@
|
|||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
#include <typeindex>
|
||||||
|
#include <typeinfo>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <version>
|
#include <version>
|
||||||
@@ -41,20 +45,15 @@
|
|||||||
# define META_HPP_NO_RTTI
|
# define META_HPP_NO_RTTI
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(META_HPP_NO_EXCEPTIONS)
|
|
||||||
# include <exception>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(META_HPP_NO_RTTI)
|
|
||||||
# include <typeindex>
|
|
||||||
# include <typeinfo>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(META_HPP_FWD)
|
#if !defined(META_HPP_FWD)
|
||||||
# define META_HPP_FWD(v) std::forward<decltype(v)>(v)
|
# define META_HPP_FWD(v) std::forward<decltype(v)>(v)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(META_HPP_ASSERT)
|
#if !defined(META_HPP_ASSERT)
|
||||||
# include <cassert>
|
|
||||||
# define META_HPP_ASSERT(...) assert(__VA_ARGS__) // NOLINT
|
# define META_HPP_ASSERT(...) assert(__VA_ARGS__) // NOLINT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !defined(META_HPP_PP_CAT)
|
||||||
|
# define META_HPP_PP_CAT(x, y) META_HPP_PP_CAT_I(x, y)
|
||||||
|
# define META_HPP_PP_CAT_I(x, y) x##y
|
||||||
|
#endif
|
||||||
|
|||||||
144
headers/meta.hpp/meta_base/defer.hpp
Normal file
144
headers/meta.hpp/meta_base/defer.hpp
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||||
|
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||||
|
* Copyright (C) 2021-2023, by Matvey Cherevko (blackmatov@gmail.com)
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "base.hpp"
|
||||||
|
|
||||||
|
namespace meta_hpp::detail::impl
|
||||||
|
{
|
||||||
|
template < typename F, typename... Args >
|
||||||
|
class defer_impl {
|
||||||
|
public:
|
||||||
|
defer_impl() = delete;
|
||||||
|
defer_impl(defer_impl&&) = delete;
|
||||||
|
defer_impl(const defer_impl&) = delete;
|
||||||
|
defer_impl& operator=(defer_impl&&) = delete;
|
||||||
|
defer_impl& operator=(const defer_impl&) = delete;
|
||||||
|
|
||||||
|
template < typename UF >
|
||||||
|
explicit defer_impl(UF&& f, std::tuple<Args...>&& args)
|
||||||
|
: f_{std::forward<UF>(f)}
|
||||||
|
, args_{std::move(args)} {}
|
||||||
|
|
||||||
|
void dismiss() noexcept {
|
||||||
|
dismissed_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
~defer_impl() noexcept {
|
||||||
|
if ( !dismissed_ ) {
|
||||||
|
std::apply(std::move(f_), std::move(args_));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
F f_;
|
||||||
|
std::tuple<Args...> args_;
|
||||||
|
bool dismissed_{};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace meta_hpp::detail
|
||||||
|
{
|
||||||
|
template < typename F, typename... Args >
|
||||||
|
class defer final : public impl::defer_impl<F, Args...> {
|
||||||
|
public:
|
||||||
|
defer() = delete;
|
||||||
|
defer(defer&&) = delete;
|
||||||
|
defer(const defer&) = delete;
|
||||||
|
defer& operator=(defer&&) = delete;
|
||||||
|
defer& operator=(const defer&) = delete;
|
||||||
|
|
||||||
|
template < typename UF >
|
||||||
|
explicit defer(UF&& f, std::tuple<Args...>&& args)
|
||||||
|
: impl::defer_impl<F, Args...>{std::forward<UF>(f), std::move(args)} {}
|
||||||
|
|
||||||
|
~defer() noexcept = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
template < typename F, typename... Args >
|
||||||
|
class error_defer final : public impl::defer_impl<F, Args...> {
|
||||||
|
public:
|
||||||
|
error_defer() = delete;
|
||||||
|
error_defer(error_defer&&) = delete;
|
||||||
|
error_defer(const error_defer&) = delete;
|
||||||
|
error_defer& operator=(error_defer&&) = delete;
|
||||||
|
error_defer& operator=(const error_defer&) = delete;
|
||||||
|
|
||||||
|
template < typename UF >
|
||||||
|
explicit error_defer(UF&& f, std::tuple<Args...>&& args)
|
||||||
|
: impl::defer_impl<F, Args...>{std::forward<UF>(f), std::move(args)}
|
||||||
|
, exceptions_{std::uncaught_exceptions()} {}
|
||||||
|
|
||||||
|
~error_defer() noexcept {
|
||||||
|
if ( exceptions_ == std::uncaught_exceptions() ) {
|
||||||
|
this->dismiss();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int exceptions_{};
|
||||||
|
};
|
||||||
|
|
||||||
|
template < typename F, typename... Args >
|
||||||
|
class return_defer final : public impl::defer_impl<F, Args...> {
|
||||||
|
public:
|
||||||
|
return_defer() = delete;
|
||||||
|
return_defer(return_defer&&) = delete;
|
||||||
|
return_defer(const return_defer&) = delete;
|
||||||
|
return_defer& operator=(return_defer&&) = delete;
|
||||||
|
return_defer& operator=(const return_defer&) = delete;
|
||||||
|
|
||||||
|
template < typename UF >
|
||||||
|
explicit return_defer(UF&& f, std::tuple<Args...>&& args)
|
||||||
|
: impl::defer_impl<F, Args...>{std::forward<UF>(f), std::move(args)}
|
||||||
|
, exceptions_{std::uncaught_exceptions()} {}
|
||||||
|
|
||||||
|
~return_defer() noexcept {
|
||||||
|
if ( exceptions_ != std::uncaught_exceptions() ) {
|
||||||
|
this->dismiss();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int exceptions_{};
|
||||||
|
};
|
||||||
|
|
||||||
|
template < typename F, typename... Args >
|
||||||
|
auto make_defer(F&& f, Args&&... args) {
|
||||||
|
using defer_t = defer<std::decay_t<F>, std::decay_t<Args>...>;
|
||||||
|
return defer_t{std::forward<F>(f), std::make_tuple(std::forward<Args>(args)...)};
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename F, typename... Args >
|
||||||
|
auto make_error_defer(F&& f, Args&&... args) {
|
||||||
|
using defer_t = error_defer<std::decay_t<F>, std::decay_t<Args>...>;
|
||||||
|
return defer_t{std::forward<F>(f), std::make_tuple(std::forward<Args>(args)...)};
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename F, typename... Args >
|
||||||
|
auto make_return_defer(F&& f, Args&&... args) {
|
||||||
|
using defer_t = return_defer<std::decay_t<F>, std::decay_t<Args>...>;
|
||||||
|
return defer_t{std::forward<F>(f), std::make_tuple(std::forward<Args>(args)...)};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __COUNTER__
|
||||||
|
# define META_HPP_DEFER(...) \
|
||||||
|
auto META_HPP_PP_CAT(meta_hpp_generated_defer_, __COUNTER__) { ::meta_hpp::detail::make_defer(__VA_ARGS__) }
|
||||||
|
# define META_HPP_ERROR_DEFER(...) \
|
||||||
|
auto META_HPP_PP_CAT(meta_hpp_generated_error_defer_, __COUNTER__) { ::meta_hpp::detail::make_error_defer(__VA_ARGS__) }
|
||||||
|
# define META_HPP_RETURN_DEFER(...) \
|
||||||
|
auto META_HPP_PP_CAT(meta_hpp_generated_return_defer_, __COUNTER__) { ::meta_hpp::detail::make_return_defer(__VA_ARGS__) }
|
||||||
|
#else
|
||||||
|
# define META_HPP_DEFER(...) \
|
||||||
|
auto META_HPP_PP_CAT(meta_hpp_generated_defer_, __LINE__) { ::meta_hpp::detail::make_defer(__VA_ARGS__) }
|
||||||
|
# define META_HPP_ERROR_DEFER(...) \
|
||||||
|
auto META_HPP_PP_CAT(meta_hpp_generated_error_defer_, __LINE__) { ::meta_hpp::detail::make_error_defer(__VA_ARGS__) }
|
||||||
|
# define META_HPP_RETURN_DEFER(...) \
|
||||||
|
auto META_HPP_PP_CAT(meta_hpp_generated_return_defer_, __LINE__) { ::meta_hpp::detail::make_return_defer(__VA_ARGS__) }
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user