defer.hpp 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. /*
  2. * Copyright (c) 2017-2023 zhllxt
  3. *
  4. * author : zhllxt
  5. * email : 37792738@qq.com
  6. *
  7. * Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. *
  10. * refrenced from https://github.com/loveyacper/ananas
  11. */
  12. #ifndef __ASIO2_DEFER_HPP__
  13. #define __ASIO2_DEFER_HPP__
  14. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #pragma once
  16. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  17. #include <functional>
  18. namespace asio2
  19. {
  20. class defer
  21. {
  22. protected:
  23. template<typename F, typename Void, typename... Args>
  24. struct is_callable : std::false_type {};
  25. template<typename F, typename... Args>
  26. struct is_callable<F, std::void_t<decltype(std::declval<std::decay_t<F>&>()
  27. ((std::declval<Args>())...)), char>, Args...> : std::true_type {};
  28. public:
  29. defer() noexcept = default;
  30. // movable
  31. defer(defer&&) noexcept = default;
  32. defer& operator=(defer&&) noexcept = default;
  33. // non copyable
  34. defer(const defer&) = delete;
  35. void operator=(const defer&) = delete;
  36. template <typename Fun, typename... Args,
  37. std::enable_if_t<is_callable<Fun, void, Args...>::value, int> = 0>
  38. defer(Fun&& fun, Args&&... args)
  39. {
  40. this->fn_ = std::bind(std::forward<Fun>(fun), std::forward<Args>(args)...);
  41. }
  42. template <typename Constructor, typename Destructor,
  43. std::enable_if_t<is_callable<Constructor, void>::value && is_callable<Destructor, void>::value, int> = 0>
  44. defer(Constructor&& ctor, Destructor&& dtor)
  45. {
  46. (ctor)();
  47. this->fn_ = std::forward<Destructor>(dtor);
  48. }
  49. ~defer() noexcept
  50. {
  51. if (this->fn_) this->fn_();
  52. }
  53. protected:
  54. std::function<void()> fn_;
  55. };
  56. #ifndef ASIO2_CONCAT
  57. #define ASIO2_CONCAT(a, b) a##b
  58. #endif
  59. #define ASIO2_MAKE_DEFER(line) ::asio2::defer ASIO2_CONCAT(_asio2_defer_, line) = [&]()
  60. #define ASIO2_DEFER ASIO2_MAKE_DEFER(__LINE__)
  61. }
  62. #endif // !__ASIO2_DEFER_HPP__