File indexing completed on 2025-04-19 08:44:21
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef BOOST_SCOPE_SCOPE_EXIT_HPP_INCLUDED_
0015 #define BOOST_SCOPE_SCOPE_EXIT_HPP_INCLUDED_
0016
0017 #include <type_traits>
0018 #include <boost/scope/detail/config.hpp>
0019 #include <boost/scope/detail/is_not_like.hpp>
0020 #include <boost/scope/detail/compact_storage.hpp>
0021 #include <boost/scope/detail/move_or_copy_construct_ref.hpp>
0022 #include <boost/scope/detail/is_nonnull_default_constructible.hpp>
0023 #include <boost/scope/detail/type_traits/conjunction.hpp>
0024 #include <boost/scope/detail/type_traits/is_invocable.hpp>
0025 #include <boost/scope/detail/type_traits/is_nothrow_invocable.hpp>
0026 #include <boost/scope/detail/header.hpp>
0027
0028 #ifdef BOOST_HAS_PRAGMA_ONCE
0029 #pragma once
0030 #endif
0031
0032 namespace boost {
0033 namespace scope {
0034
0035 template< typename Func, typename Cond >
0036 class scope_exit;
0037
0038 namespace detail {
0039
0040
0041 template< typename T >
0042 using is_not_like_scope_exit = detail::is_not_like< T, scope_exit >;
0043
0044
0045 template< typename Func, typename Cond >
0046 class init_guard
0047 {
0048 private:
0049 Func& m_func;
0050 Cond& m_cond;
0051 bool m_active;
0052
0053 public:
0054 init_guard(Func& func, Cond& cond, bool active) noexcept :
0055 m_func(func),
0056 m_cond(cond),
0057 m_active(active)
0058 {
0059 }
0060
0061 init_guard(init_guard const&) = delete;
0062 init_guard& operator= (init_guard const&) = delete;
0063
0064 ~init_guard()
0065 noexcept(detail::conjunction<
0066 detail::is_nothrow_invocable< Func& >,
0067 detail::is_nothrow_invocable< Cond& >
0068 >::value)
0069 {
0070 if (m_active && m_cond())
0071 m_func();
0072 }
0073
0074 Func&& get_func() noexcept
0075 {
0076 return static_cast< Func&& >(m_func);
0077 }
0078
0079 Cond&& get_cond() noexcept
0080 {
0081 return static_cast< Cond&& >(m_cond);
0082 }
0083
0084 void deactivate() noexcept
0085 {
0086 m_active = false;
0087 }
0088 };
0089
0090 }
0091
0092
0093
0094
0095
0096
0097
0098 class always_true
0099 {
0100 public:
0101
0102 using result_type = bool;
0103
0104
0105
0106
0107
0108
0109 result_type operator()() const noexcept
0110 {
0111 return true;
0112 }
0113 };
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150 template< typename Func, typename Cond = always_true >
0151 class scope_exit
0152 {
0153
0154 private:
0155 struct func_holder :
0156 public detail::compact_storage< Func >
0157 {
0158 using func_base = detail::compact_storage< Func >;
0159
0160 template<
0161 typename F,
0162 typename C,
0163 typename = typename std::enable_if< std::is_constructible< Func, F >::value >::type
0164 >
0165 explicit func_holder(F&& func, C&& cond, bool active, std::true_type) noexcept :
0166 func_base(static_cast< F&& >(func))
0167 {
0168 }
0169
0170 template<
0171 typename F,
0172 typename C,
0173 typename = typename std::enable_if< std::is_constructible< Func, F >::value >::type
0174 >
0175 explicit func_holder(F&& func, C&& cond, bool active, std::false_type) :
0176 func_holder(detail::init_guard< F, C >(func, cond, active))
0177 {
0178 }
0179
0180 private:
0181 template< typename F, typename C >
0182 explicit func_holder(detail::init_guard< F, C >&& init) :
0183 func_base(init.get_func())
0184 {
0185 init.deactivate();
0186 }
0187 };
0188
0189 struct cond_holder :
0190 public detail::compact_storage< Cond >
0191 {
0192 using cond_base = detail::compact_storage< Cond >;
0193
0194 template<
0195 typename C,
0196 typename = typename std::enable_if< std::is_constructible< Cond, C >::value >::type
0197 >
0198 explicit cond_holder(C&& cond, Func& func, bool active, std::true_type) noexcept :
0199 cond_base(static_cast< C&& >(cond))
0200 {
0201 }
0202
0203 template<
0204 typename C,
0205 typename = typename std::enable_if< std::is_constructible< Cond, C >::value >::type
0206 >
0207 explicit cond_holder(C&& cond, Func& func, bool active, std::false_type) :
0208 cond_holder(detail::init_guard< Func&, C >(func, cond, active))
0209 {
0210 }
0211
0212 private:
0213 template< typename C >
0214 explicit cond_holder(detail::init_guard< Func&, C >&& init) :
0215 cond_base(init.get_cond())
0216 {
0217 init.deactivate();
0218 }
0219 };
0220
0221 struct data :
0222 public func_holder,
0223 public cond_holder
0224 {
0225 bool m_active;
0226
0227 template<
0228 typename F,
0229 typename C,
0230 typename = typename std::enable_if< detail::conjunction<
0231 std::is_constructible< func_holder, F, C, bool, typename std::is_nothrow_constructible< Func, F >::type >,
0232 std::is_constructible< cond_holder, C, Func&, bool, typename std::is_nothrow_constructible< Cond, C >::type >
0233 >::value >::type
0234 >
0235 explicit data(F&& func, C&& cond, bool active)
0236 noexcept(detail::conjunction< std::is_nothrow_constructible< Func, F >, std::is_nothrow_constructible< Cond, C > >::value) :
0237 func_holder(static_cast< F&& >(func), static_cast< C&& >(cond), active, typename std::is_nothrow_constructible< Func, F >::type()),
0238 cond_holder(static_cast< C&& >(cond), func_holder::get(), active, typename std::is_nothrow_constructible< Cond, C >::type()),
0239 m_active(active)
0240 {
0241 }
0242
0243 Func& get_func() noexcept
0244 {
0245 return func_holder::get();
0246 }
0247
0248 Func const& get_func() const noexcept
0249 {
0250 return func_holder::get();
0251 }
0252
0253 Cond& get_cond() noexcept
0254 {
0255 return cond_holder::get();
0256 }
0257
0258 Cond const& get_cond() const noexcept
0259 {
0260 return cond_holder::get();
0261 }
0262
0263 bool deactivate() noexcept
0264 {
0265 bool active = m_active;
0266 m_active = false;
0267 return active;
0268 }
0269 };
0270
0271 data m_data;
0272
0273
0274 public:
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295 template<
0296 typename F
0297
0298 , typename = typename std::enable_if< detail::conjunction<
0299 detail::is_nothrow_nonnull_default_constructible< Cond >,
0300 std::is_constructible<
0301 data,
0302 typename detail::move_or_copy_construct_ref< F, Func >::type,
0303 typename detail::move_or_copy_construct_ref< Cond >::type,
0304 bool
0305 >,
0306 detail::is_not_like_scope_exit< F >
0307 >::value >::type
0308
0309 >
0310 explicit scope_exit(F&& func, bool active = true)
0311 noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(
0312 std::is_nothrow_constructible<
0313 data,
0314 typename detail::move_or_copy_construct_ref< F, Func >::type,
0315 typename detail::move_or_copy_construct_ref< Cond >::type,
0316 bool
0317 >::value
0318 )) :
0319 m_data
0320 (
0321 static_cast< typename detail::move_or_copy_construct_ref< F, Func >::type >(func),
0322 static_cast< typename detail::move_or_copy_construct_ref< Cond >::type >(Cond()),
0323 active
0324 )
0325 {
0326 }
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349 template<
0350 typename F,
0351 typename C
0352
0353 , typename = typename std::enable_if< detail::conjunction<
0354 detail::is_invocable< C const& >,
0355 std::is_constructible<
0356 data,
0357 typename detail::move_or_copy_construct_ref< F, Func >::type,
0358 typename detail::move_or_copy_construct_ref< C, Cond >::type,
0359 bool
0360 >
0361 >::value >::type
0362
0363 >
0364 explicit scope_exit(F&& func, C&& cond, bool active = true)
0365 noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(
0366 std::is_nothrow_constructible<
0367 data,
0368 typename detail::move_or_copy_construct_ref< F, Func >::type,
0369 typename detail::move_or_copy_construct_ref< C, Cond >::type,
0370 bool
0371 >::value
0372 )) :
0373 m_data
0374 (
0375 static_cast< typename detail::move_or_copy_construct_ref< F, Func >::type >(func),
0376 static_cast< typename detail::move_or_copy_construct_ref< C, Cond >::type >(cond),
0377 active
0378 )
0379 {
0380 }
0381
0382
0383
0384
0385
0386
0387
0388
0389
0390
0391
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401
0402
0403
0404
0405
0406 template<
0407 bool Requires = std::is_constructible<
0408 data,
0409 typename detail::move_or_copy_construct_ref< Func >::type,
0410 typename detail::move_or_copy_construct_ref< Cond >::type,
0411 bool
0412 >::value,
0413 typename = typename std::enable_if< Requires >::type
0414 >
0415
0416 scope_exit(scope_exit&& that)
0417 noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(
0418 std::is_nothrow_constructible<
0419 data,
0420 typename detail::move_or_copy_construct_ref< Func >::type,
0421 typename detail::move_or_copy_construct_ref< Cond >::type,
0422 bool
0423 >::value
0424 )) :
0425 m_data
0426 (
0427 static_cast< typename detail::move_or_copy_construct_ref< Func >::type >(that.m_data.get_func()),
0428 static_cast< typename detail::move_or_copy_construct_ref< Cond >::type >(that.m_data.get_cond()),
0429 that.m_data.deactivate()
0430 )
0431 {
0432 }
0433
0434 scope_exit& operator= (scope_exit&&) = delete;
0435
0436 scope_exit(scope_exit const&) = delete;
0437 scope_exit& operator= (scope_exit const&) = delete;
0438
0439
0440
0441
0442
0443
0444
0445 ~scope_exit()
0446 noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(
0447 detail::conjunction<
0448 detail::is_nothrow_invocable< Func& >,
0449 detail::is_nothrow_invocable< Cond& >
0450 >::value
0451 ))
0452 {
0453 if (BOOST_LIKELY(m_data.m_active && m_data.get_cond()()))
0454 m_data.get_func()();
0455 }
0456
0457
0458
0459
0460
0461
0462
0463
0464 bool active() const noexcept
0465 {
0466 return m_data.m_active;
0467 }
0468
0469
0470
0471
0472
0473
0474
0475
0476
0477
0478 void set_active(bool active) noexcept
0479 {
0480 m_data.m_active = active;
0481 }
0482 };
0483
0484 #if !defined(BOOST_NO_CXX17_DEDUCTION_GUIDES)
0485 template< typename Func >
0486 explicit scope_exit(Func) -> scope_exit< Func >;
0487
0488 template< typename Func >
0489 explicit scope_exit(Func, bool) -> scope_exit< Func >;
0490
0491 template< typename Func, typename Cond >
0492 explicit scope_exit(Func, Cond) -> scope_exit< Func, Cond >;
0493
0494 template< typename Func, typename Cond >
0495 explicit scope_exit(Func, Cond, bool) -> scope_exit< Func, Cond >;
0496 #endif
0497
0498
0499
0500
0501
0502
0503
0504
0505
0506
0507 template< typename F >
0508 inline scope_exit< typename std::decay< F >::type > make_scope_exit(F&& func, bool active = true)
0509 noexcept(std::is_nothrow_constructible<
0510 scope_exit< typename std::decay< F >::type >,
0511 F,
0512 bool
0513 >::value)
0514 {
0515 return scope_exit< typename std::decay< F >::type >(static_cast< F&& >(func), active);
0516 }
0517
0518
0519
0520
0521
0522
0523
0524
0525
0526
0527
0528
0529 template< typename F, typename C >
0530 inline
0531 #if !defined(BOOST_SCOPE_DOXYGEN)
0532 typename std::enable_if<
0533 std::is_constructible<
0534 scope_exit< typename std::decay< F >::type, typename std::decay< C >::type >,
0535 F,
0536 C,
0537 bool
0538 >::value,
0539 scope_exit< typename std::decay< F >::type, typename std::decay< C >::type >
0540 >::type
0541 #else
0542 scope_exit< typename std::decay< F >::type, typename std::decay< C >::type >
0543 #endif
0544 make_scope_exit(F&& func, C&& cond, bool active = true)
0545 noexcept(std::is_nothrow_constructible<
0546 scope_exit< typename std::decay< F >::type, typename std::decay< C >::type >,
0547 F,
0548 C,
0549 bool
0550 >::value)
0551 {
0552 return scope_exit< typename std::decay< F >::type, typename std::decay< C >::type >(static_cast< F&& >(func), static_cast< C&& >(cond), active);
0553 }
0554
0555 }
0556 }
0557
0558 #include <boost/scope/detail/footer.hpp>
0559
0560 #endif