Horizon
scope_exit.hpp
Go to the documentation of this file.
1 // Range v3 library
3 //
4 // Copyright Eric Niebler 2017-present
5 //
6 // Use, modification and distribution is subject to the
7 // Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at
9 // http://www.boost.org/LICENSE_1_0.txt)
10 //
11 // Project home: https://github.com/ericniebler/range-v3
12 //
13 #ifndef RANGES_V3_UTILITY_SCOPE_EXIT_HPP
14 #define RANGES_V3_UTILITY_SCOPE_EXIT_HPP
15 
16 #include <functional>
17 #include <type_traits>
18 #include <utility>
19 
20 #include <meta/meta.hpp>
21 
22 #include <range/v3/detail/prologue.hpp>
23 
24 namespace ranges
25 {
26  template<typename Fun>
27  struct scope_exit
28  {
29  private:
30  using nothrow_move_t = std::is_nothrow_move_constructible<Fun>;
31  using nothrow_copy_t = std::is_nothrow_copy_constructible<Fun>;
32 
33  Fun fun_;
34  bool dismissed_{false};
35 
36  using ref_t = decltype(std::ref(std::declval<Fun const &>()));
37  using guard = scope_exit<ref_t>;
38 
39  scope_exit(Fun const & fun, guard && g)
40  : fun_(fun)
41  {
42  g.dismiss();
43  }
44 
45  scope_exit(Fun const & fun, std::false_type)
46  : scope_exit(fun, guard{std::ref(fun)})
47  {}
48 
49  scope_exit(Fun const & fun, std::true_type) noexcept
50  : fun_(fun)
51  {}
52 
53  scope_exit(Fun && fun, std::true_type) noexcept
54  : fun_(std::move(fun))
55  {}
56 
57  public:
58  explicit scope_exit(Fun const & fun) noexcept(
59  noexcept(scope_exit(fun, nothrow_copy_t{})))
60  : scope_exit(fun, nothrow_copy_t{})
61  {}
62 
63  explicit scope_exit(Fun && fun) noexcept(noexcept(scope_exit(std::move(fun),
64  nothrow_move_t{})))
65  : scope_exit(std::move(fun), nothrow_move_t{})
66  {}
67 
68  scope_exit(scope_exit const &) = delete;
69 
70  scope_exit(scope_exit && that) noexcept(
71  std::is_nothrow_move_constructible<Fun>::value)
72  : scope_exit(std::move((that.dismiss(), that)).fun_)
73  {}
74 
75  ~scope_exit()
76  {
77  if(!dismissed_)
78  fun_();
79  }
80 
81  void dismiss() noexcept
82  {
83  dismissed_ = true;
84  }
85  };
86 
87  template<typename Fun, typename ScopeExit = scope_exit<meta::_t<std::decay<Fun>>>>
88  ScopeExit make_scope_exit(Fun && fun) noexcept(
89  noexcept(ScopeExit(ScopeExit((Fun &&) fun))))
90  {
91  return ScopeExit((Fun &&) fun);
92  }
93 } // namespace ranges
94 
95 #include <range/v3/detail/epilogue.hpp>
96 
97 #endif
Tiny meta-programming library.
Definition: scope_exit.hpp:28