File indexing completed on 2025-04-19 08:44:22
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef BOOST_SCOPE_UNIQUE_RESOURCE_HPP_INCLUDED_
0015 #define BOOST_SCOPE_UNIQUE_RESOURCE_HPP_INCLUDED_
0016
0017 #include <new> // for placement new
0018 #include <type_traits>
0019 #include <boost/core/addressof.hpp>
0020 #include <boost/core/invoke_swap.hpp>
0021 #include <boost/scope/unique_resource_fwd.hpp>
0022 #include <boost/scope/detail/config.hpp>
0023 #include <boost/scope/detail/compact_storage.hpp>
0024 #include <boost/scope/detail/move_or_copy_assign_ref.hpp>
0025 #include <boost/scope/detail/move_or_copy_construct_ref.hpp>
0026 #include <boost/scope/detail/is_nonnull_default_constructible.hpp>
0027 #include <boost/scope/detail/type_traits/is_swappable.hpp>
0028 #include <boost/scope/detail/type_traits/is_nothrow_swappable.hpp>
0029 #include <boost/scope/detail/type_traits/is_nothrow_invocable.hpp>
0030 #include <boost/scope/detail/type_traits/negation.hpp>
0031 #include <boost/scope/detail/type_traits/conjunction.hpp>
0032 #include <boost/scope/detail/type_traits/disjunction.hpp>
0033 #include <boost/scope/detail/header.hpp>
0034
0035 #ifdef BOOST_HAS_PRAGMA_ONCE
0036 #pragma once
0037 #endif
0038
0039 namespace boost {
0040 namespace scope {
0041
0042 #if !defined(BOOST_NO_CXX17_FOLD_EXPRESSIONS) && !defined(BOOST_NO_CXX17_AUTO_NONTYPE_TEMPLATE_PARAMS)
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058 template< auto DefaultValue, auto... UnallocatedValues >
0059 struct unallocated_resource
0060 {
0061
0062 static decltype(DefaultValue) make_default() noexcept
0063 {
0064 return DefaultValue;
0065 }
0066
0067
0068 template< typename Resource >
0069 static bool is_allocated(Resource const& res) noexcept
0070 {
0071 static_assert(noexcept(res != DefaultValue && (... && (res != UnallocatedValues))),
0072 "Invalid unallocated resource value types: comparing resource values with the unallocated values must be noexcept");
0073 return res != DefaultValue && (... && (res != UnallocatedValues));
0074 }
0075 };
0076
0077 #endif
0078
0079 struct default_resource_t { };
0080
0081
0082 BOOST_INLINE_VARIABLE constexpr default_resource_t default_resource = { };
0083
0084 namespace detail {
0085
0086
0087 template< typename T >
0088 struct is_default_resource : public std::false_type { };
0089 template< >
0090 struct is_default_resource< default_resource_t > : public std::true_type { };
0091 template< >
0092 struct is_default_resource< const default_resource_t > : public std::true_type { };
0093 template< >
0094 struct is_default_resource< volatile default_resource_t > : public std::true_type { };
0095 template< >
0096 struct is_default_resource< const volatile default_resource_t > : public std::true_type { };
0097 template< typename T >
0098 struct is_default_resource< T& > : public is_default_resource< T >::type { };
0099
0100
0101 template< typename T >
0102 class ref_wrapper
0103 {
0104 private:
0105 T* m_value;
0106
0107 public:
0108 explicit
0109 #if !defined(BOOST_CORE_NO_CONSTEXPR_ADDRESSOF)
0110 constexpr
0111 #endif
0112 ref_wrapper(T& value) noexcept :
0113 m_value(boost::addressof(value))
0114 {
0115 }
0116
0117 ref_wrapper& operator= (T& value) noexcept
0118 {
0119 m_value = boost::addressof(value);
0120 return *this;
0121 }
0122
0123 ref_wrapper(T&&) = delete;
0124 ref_wrapper& operator= (T&&) = delete;
0125
0126 operator T& () const noexcept
0127 {
0128 return *m_value;
0129 }
0130
0131 template< typename... Args >
0132 void operator() (Args&&... args) const noexcept(detail::is_nothrow_invocable< T&, Args&&... >::value)
0133 {
0134 (*m_value)(static_cast< Args&& >(args)...);
0135 }
0136 };
0137
0138 template< typename T >
0139 struct wrap_reference
0140 {
0141 using type = T;
0142 };
0143
0144 template< typename T >
0145 struct wrap_reference< T& >
0146 {
0147 using type = ref_wrapper< T >;
0148 };
0149
0150 template< typename Resource, bool UseCompactStorage >
0151 class resource_holder :
0152 public detail::compact_storage< typename wrap_reference< Resource >::type >
0153 {
0154 public:
0155 using resource_type = Resource;
0156 using internal_resource_type = typename wrap_reference< resource_type >::type;
0157
0158 private:
0159 using resource_base = detail::compact_storage< internal_resource_type >;
0160
0161 public:
0162 template<
0163 bool Requires = std::is_default_constructible< internal_resource_type >::value,
0164 typename = typename std::enable_if< Requires >::type
0165 >
0166 constexpr resource_holder() noexcept(std::is_nothrow_default_constructible< internal_resource_type >::value) :
0167 resource_base()
0168 {
0169 }
0170
0171 template<
0172 typename R,
0173 typename = typename std::enable_if< std::is_constructible< internal_resource_type, R >::value >::type
0174 >
0175 explicit resource_holder(R&& res) noexcept(std::is_nothrow_constructible< internal_resource_type, R >::value) :
0176 resource_base(static_cast< R&& >(res))
0177 {
0178 }
0179
0180 template<
0181 typename R,
0182 typename D,
0183 typename = typename std::enable_if< std::is_constructible< internal_resource_type, R >::value >::type
0184 >
0185 explicit resource_holder(R&& res, D&& del, bool allocated) noexcept(std::is_nothrow_constructible< internal_resource_type, R >::value) :
0186 resource_holder(static_cast< R&& >(res), static_cast< D&& >(del), allocated, typename std::is_nothrow_constructible< resource_type, R >::type())
0187 {
0188 }
0189
0190 resource_type& get() noexcept
0191 {
0192 return resource_base::get();
0193 }
0194
0195 resource_type const& get() const noexcept
0196 {
0197 return resource_base::get();
0198 }
0199
0200 internal_resource_type& get_internal() noexcept
0201 {
0202 return resource_base::get();
0203 }
0204
0205 internal_resource_type const& get_internal() const noexcept
0206 {
0207 return resource_base::get();
0208 }
0209
0210 void move_from(internal_resource_type&& that) noexcept(std::is_nothrow_move_assignable< internal_resource_type >::value)
0211 {
0212 resource_base::get() = static_cast< internal_resource_type&& >(that);
0213 }
0214
0215 private:
0216 template< typename R, typename D >
0217 explicit resource_holder(R&& res, D&& del, bool allocated, std::true_type) noexcept :
0218 resource_base(static_cast< R&& >(res))
0219 {
0220 }
0221
0222 template< typename R, typename D >
0223 explicit resource_holder(R&& res, D&& del, bool allocated, std::false_type) try :
0224 resource_base(res)
0225 {
0226 }
0227 catch (...)
0228 {
0229 if (allocated)
0230 del(res);
0231 }
0232 };
0233
0234 template< typename Resource >
0235 class resource_holder< Resource, false >
0236 {
0237 public:
0238 using resource_type = Resource;
0239 using internal_resource_type = typename wrap_reference< resource_type >::type;
0240
0241 private:
0242
0243 internal_resource_type m_resource;
0244
0245 public:
0246 template<
0247 bool Requires = std::is_default_constructible< internal_resource_type >::value,
0248 typename = typename std::enable_if< Requires >::type
0249 >
0250 constexpr resource_holder() noexcept(std::is_nothrow_default_constructible< internal_resource_type >::value) :
0251 m_resource()
0252 {
0253 }
0254
0255 template<
0256 typename R,
0257 typename = typename std::enable_if< std::is_constructible< internal_resource_type, R >::value >::type
0258 >
0259 explicit resource_holder(R&& res) noexcept(std::is_nothrow_constructible< internal_resource_type, R >::value) :
0260 m_resource(static_cast< R&& >(res))
0261 {
0262 }
0263
0264 template<
0265 typename R,
0266 typename D,
0267 typename = typename std::enable_if< std::is_constructible< internal_resource_type, R >::value >::type
0268 >
0269 explicit resource_holder(R&& res, D&& del, bool allocated) noexcept(std::is_nothrow_constructible< internal_resource_type, R >::value) :
0270 resource_holder(static_cast< R&& >(res), static_cast< D&& >(del), allocated, typename std::is_nothrow_constructible< resource_type, R >::type())
0271 {
0272 }
0273
0274 resource_type& get() noexcept
0275 {
0276 return m_resource;
0277 }
0278
0279 resource_type const& get() const noexcept
0280 {
0281 return m_resource;
0282 }
0283
0284 internal_resource_type& get_internal() noexcept
0285 {
0286 return m_resource;
0287 }
0288
0289 internal_resource_type const& get_internal() const noexcept
0290 {
0291 return m_resource;
0292 }
0293
0294 void move_from(internal_resource_type&& that)
0295 noexcept(std::is_nothrow_constructible< internal_resource_type, typename detail::move_or_copy_construct_ref< resource_type >::type >::value)
0296 {
0297 internal_resource_type* p = boost::addressof(m_resource);
0298 p->~internal_resource_type();
0299 new (p) internal_resource_type(static_cast< typename detail::move_or_copy_construct_ref< resource_type >::type >(that));
0300 }
0301
0302 private:
0303 template< typename R, typename D >
0304 explicit resource_holder(R&& res, D&& del, bool allocated, std::true_type) noexcept :
0305 m_resource(static_cast< R&& >(res))
0306 {
0307 }
0308
0309 template< typename R, typename D >
0310 explicit resource_holder(R&& res, D&& del, bool allocated, std::false_type) try :
0311 m_resource(res)
0312 {
0313 }
0314 catch (...)
0315 {
0316 if (allocated)
0317 del(res);
0318 }
0319 };
0320
0321 template< typename Resource, typename Deleter >
0322 class deleter_holder :
0323 public detail::compact_storage< typename wrap_reference< Deleter >::type >
0324 {
0325 public:
0326 using resource_type = Resource;
0327 using deleter_type = Deleter;
0328 using internal_deleter_type = typename wrap_reference< deleter_type >::type;
0329
0330 private:
0331 using deleter_base = detail::compact_storage< internal_deleter_type >;
0332
0333 public:
0334 template<
0335 bool Requires = detail::is_nonnull_default_constructible< internal_deleter_type >::value,
0336 typename = typename std::enable_if< Requires >::type
0337 >
0338 constexpr deleter_holder() noexcept(detail::is_nothrow_nonnull_default_constructible< internal_deleter_type >::value) :
0339 deleter_base()
0340 {
0341 }
0342
0343 template<
0344 typename D,
0345 typename = typename std::enable_if< std::is_constructible< internal_deleter_type, D >::value >::type
0346 >
0347 explicit deleter_holder(D&& del) noexcept(std::is_nothrow_constructible< internal_deleter_type, D >::value) :
0348 deleter_base(static_cast< D&& >(del))
0349 {
0350 }
0351
0352 template<
0353 typename D,
0354 typename = typename std::enable_if< std::is_constructible< internal_deleter_type, D >::value >::type
0355 >
0356 explicit deleter_holder(D&& del, resource_type& res, bool allocated) noexcept(std::is_nothrow_constructible< internal_deleter_type, D >::value) :
0357 deleter_holder(static_cast< D&& >(del), res, allocated, typename std::is_nothrow_constructible< internal_deleter_type, D >::type())
0358 {
0359 }
0360
0361 deleter_type& get() noexcept
0362 {
0363 return deleter_base::get();
0364 }
0365
0366 deleter_type const& get() const noexcept
0367 {
0368 return deleter_base::get();
0369 }
0370
0371 internal_deleter_type& get_internal() noexcept
0372 {
0373 return deleter_base::get();
0374 }
0375
0376 internal_deleter_type const& get_internal() const noexcept
0377 {
0378 return deleter_base::get();
0379 }
0380
0381 private:
0382 template< typename D >
0383 explicit deleter_holder(D&& del, resource_type& res, bool allocated, std::true_type) noexcept :
0384 deleter_base(static_cast< D&& >(del))
0385 {
0386 }
0387
0388 template< typename D >
0389 explicit deleter_holder(D&& del, resource_type& res, bool allocated, std::false_type) try :
0390 deleter_base(del)
0391 {
0392 }
0393 catch (...)
0394 {
0395 if (BOOST_LIKELY(allocated))
0396 del(res);
0397 }
0398 };
0399
0400
0401
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418
0419
0420
0421
0422
0423
0424
0425
0426
0427
0428
0429
0430
0431 template< typename Resource, typename Deleter >
0432 using use_resource_compact_storage = detail::disjunction<
0433 std::is_nothrow_move_assignable< typename wrap_reference< Resource >::type >,
0434 std::is_nothrow_constructible< typename wrap_reference< Deleter >::type, typename detail::move_or_copy_construct_ref< Deleter >::type >,
0435 detail::negation< std::is_nothrow_constructible< typename wrap_reference< Resource >::type, typename detail::move_or_copy_construct_ref< Resource >::type > >
0436 >;
0437
0438 template< typename Resource, typename Deleter, typename Traits >
0439 class unique_resource_data :
0440 public detail::resource_holder< Resource, use_resource_compact_storage< Resource, Deleter >::value >,
0441 public detail::deleter_holder< Resource, Deleter >
0442 {
0443 public:
0444 using resource_type = Resource;
0445 using deleter_type = Deleter;
0446 using traits_type = Traits;
0447
0448 private:
0449 using resource_holder = detail::resource_holder< resource_type, use_resource_compact_storage< resource_type, deleter_type >::value >;
0450 using deleter_holder = detail::deleter_holder< resource_type, deleter_type >;
0451 using result_of_make_default = decltype(traits_type::make_default());
0452
0453 public:
0454 using internal_resource_type = typename resource_holder::internal_resource_type;
0455 using internal_deleter_type = typename deleter_holder::internal_deleter_type;
0456
0457 static_assert(noexcept(traits_type::make_default()), "Invalid unique_resource resource traits: make_default must be noexcept");
0458 static_assert(std::is_nothrow_assignable< internal_resource_type&, result_of_make_default >::value,
0459 "Invalid unique_resource resource traits: resource must be nothrow-assignable from the result of make_default");
0460 static_assert(noexcept(traits_type::is_allocated(std::declval< resource_type const& >())), "Invalid unique_resource resource traits: is_allocated must be noexcept");
0461
0462 public:
0463 template<
0464 bool Requires = detail::conjunction<
0465 std::is_constructible< resource_holder, result_of_make_default >,
0466 std::is_default_constructible< deleter_holder >
0467 >::value,
0468 typename = typename std::enable_if< Requires >::type
0469 >
0470 constexpr unique_resource_data()
0471 noexcept(detail::conjunction<
0472 std::is_nothrow_constructible< resource_holder, result_of_make_default >,
0473 std::is_nothrow_default_constructible< deleter_holder >
0474 >::value) :
0475 resource_holder(traits_type::make_default()),
0476 deleter_holder()
0477 {
0478 }
0479
0480 unique_resource_data(unique_resource_data const&) = delete;
0481 unique_resource_data& operator= (unique_resource_data const&) = delete;
0482
0483 unique_resource_data(unique_resource_data&& that)
0484 noexcept(detail::conjunction<
0485 std::is_nothrow_constructible< internal_resource_type, typename detail::move_or_copy_construct_ref< resource_type >::type >,
0486 std::is_nothrow_constructible< internal_deleter_type, typename detail::move_or_copy_construct_ref< deleter_type >::type >
0487 >::value) :
0488 unique_resource_data
0489 (
0490 static_cast< unique_resource_data&& >(that),
0491 typename std::is_nothrow_constructible< internal_resource_type, typename detail::move_or_copy_construct_ref< resource_type >::type >::type(),
0492 typename std::is_nothrow_constructible< internal_deleter_type, typename detail::move_or_copy_construct_ref< deleter_type >::type >::type()
0493 )
0494 {
0495 }
0496
0497 template<
0498 typename D,
0499 typename = typename std::enable_if< detail::conjunction<
0500 std::is_constructible< resource_holder, result_of_make_default >,
0501 std::is_constructible< deleter_holder, D >
0502 >::value >::type
0503 >
0504 explicit unique_resource_data(default_resource_t, D&& del)
0505 noexcept(detail::conjunction<
0506 std::is_nothrow_constructible< resource_holder, result_of_make_default >,
0507 std::is_nothrow_constructible< deleter_holder, D >
0508 >::value) :
0509 resource_holder(traits_type::make_default()),
0510 deleter_holder(static_cast< D&& >(del))
0511 {
0512 }
0513
0514 template<
0515 typename R,
0516 typename D,
0517 typename = typename std::enable_if< detail::conjunction<
0518 detail::negation< detail::is_default_resource< R > >,
0519 std::is_constructible< resource_holder, R, D, bool >,
0520 std::is_constructible< deleter_holder, D, resource_type&, bool >
0521 >::value >::type
0522 >
0523 explicit unique_resource_data(R&& res, D&& del)
0524 noexcept(detail::conjunction<
0525 std::is_nothrow_constructible< resource_holder, R, D, bool >,
0526 std::is_nothrow_constructible< deleter_holder, D, resource_type&, bool >
0527 >::value) :
0528 unique_resource_data(static_cast< R&& >(res), static_cast< D&& >(del), traits_type::is_allocated(res))
0529 {
0530
0531
0532 static_assert(noexcept(traits_type::is_allocated(res)), "Invalid unique_resource resource traits: is_allocated must be noexcept");
0533 }
0534
0535 template<
0536 bool Requires = detail::conjunction<
0537 std::is_assignable< internal_resource_type&, typename detail::move_or_copy_assign_ref< resource_type >::type >,
0538 std::is_assignable< internal_deleter_type&, typename detail::move_or_copy_assign_ref< deleter_type >::type >
0539 >::value
0540 >
0541 typename std::enable_if< Requires, unique_resource_data& >::type operator= (unique_resource_data&& that)
0542 noexcept(detail::conjunction<
0543 std::is_nothrow_assignable< internal_resource_type&, typename detail::move_or_copy_assign_ref< resource_type >::type >,
0544 std::is_nothrow_assignable< internal_deleter_type&, typename detail::move_or_copy_assign_ref< deleter_type >::type >
0545 >::value)
0546 {
0547 assign(static_cast< unique_resource_data&& >(that), typename std::is_nothrow_move_assignable< internal_deleter_type >::type());
0548 return *this;
0549 }
0550
0551 resource_type& get_resource() noexcept
0552 {
0553 return resource_holder::get();
0554 }
0555
0556 resource_type const& get_resource() const noexcept
0557 {
0558 return resource_holder::get();
0559 }
0560
0561 internal_resource_type& get_internal_resource() noexcept
0562 {
0563 return resource_holder::get_internal();
0564 }
0565
0566 internal_resource_type const& get_internal_resource() const noexcept
0567 {
0568 return resource_holder::get_internal();
0569 }
0570
0571 deleter_type& get_deleter() noexcept
0572 {
0573 return deleter_holder::get();
0574 }
0575
0576 deleter_type const& get_deleter() const noexcept
0577 {
0578 return deleter_holder::get();
0579 }
0580
0581 internal_deleter_type& get_internal_deleter() noexcept
0582 {
0583 return deleter_holder::get_internal();
0584 }
0585
0586 internal_deleter_type const& get_internal_deleter() const noexcept
0587 {
0588 return deleter_holder::get_internal();
0589 }
0590
0591 bool is_allocated() const noexcept
0592 {
0593 return traits_type::is_allocated(get_resource());
0594 }
0595
0596 void set_unallocated() noexcept
0597 {
0598 get_internal_resource() = traits_type::make_default();
0599 }
0600
0601 template< typename R >
0602 void assign_resource(R&& res) noexcept(std::is_nothrow_assignable< internal_resource_type&, R >::value)
0603 {
0604 get_internal_resource() = static_cast< R&& >(res);
0605 }
0606
0607 template<
0608 bool Requires = detail::conjunction<
0609 detail::is_swappable< internal_resource_type >,
0610 detail::is_swappable< internal_deleter_type >,
0611 detail::disjunction<
0612 detail::is_nothrow_swappable< internal_resource_type >,
0613 detail::is_nothrow_swappable< internal_deleter_type >
0614 >
0615 >::value
0616 >
0617 typename std::enable_if< Requires >::type swap(unique_resource_data& that)
0618 noexcept(detail::conjunction< detail::is_nothrow_swappable< internal_resource_type >, detail::is_nothrow_swappable< internal_deleter_type > >::value)
0619 {
0620 swap_impl
0621 (
0622 that,
0623 std::integral_constant< bool, detail::is_nothrow_swappable< internal_resource_type >::value >(),
0624 std::integral_constant< bool, detail::conjunction<
0625 detail::is_nothrow_swappable< internal_resource_type >,
0626 detail::is_nothrow_swappable< internal_deleter_type >
0627 >::value >()
0628 );
0629 }
0630
0631 private:
0632 unique_resource_data(unique_resource_data&& that, std::true_type, std::true_type) noexcept :
0633 resource_holder(static_cast< typename detail::move_or_copy_construct_ref< resource_type >::type >(that.get_resource())),
0634 deleter_holder(static_cast< typename detail::move_or_copy_construct_ref< deleter_type >::type >(that.get_deleter()))
0635 {
0636 that.set_unallocated();
0637 }
0638
0639 unique_resource_data(unique_resource_data&& that, std::false_type, std::true_type) :
0640 resource_holder(static_cast< resource_type const& >(that.get_resource())),
0641 deleter_holder(static_cast< typename detail::move_or_copy_construct_ref< deleter_type >::type >(that.get_deleter()))
0642 {
0643 that.set_unallocated();
0644 }
0645
0646 unique_resource_data(unique_resource_data&& that, std::true_type, std::false_type) try :
0647 resource_holder(static_cast< typename detail::move_or_copy_construct_ref< resource_type >::type >(that.get_resource())),
0648 deleter_holder(static_cast< deleter_type const& >(that.get_deleter()))
0649 {
0650 that.set_unallocated();
0651 }
0652 catch (...)
0653 {
0654
0655
0656 that.resource_holder::move_from(static_cast< internal_resource_type&& >(resource_holder::get_internal()));
0657 }
0658
0659 unique_resource_data(unique_resource_data&& that, std::false_type, std::false_type) :
0660 resource_holder(static_cast< resource_type const& >(that.get_resource())),
0661 deleter_holder(static_cast< deleter_type const& >(that.get_deleter()))
0662 {
0663 that.set_unallocated();
0664 }
0665
0666 template<
0667 typename R,
0668 typename D,
0669 typename = typename std::enable_if< detail::conjunction<
0670 std::is_constructible< resource_holder, R, D, bool >,
0671 std::is_constructible< deleter_holder, D, resource_type&, bool >
0672 >::value >::type
0673 >
0674 explicit unique_resource_data(R&& res, D&& del, bool allocated)
0675 noexcept(detail::conjunction<
0676 std::is_nothrow_constructible< resource_holder, R, D, bool >,
0677 std::is_nothrow_constructible< deleter_holder, D, resource_type&, bool >
0678 >::value) :
0679 resource_holder(static_cast< R&& >(res), static_cast< D&& >(del), allocated),
0680 deleter_holder(static_cast< D&& >(del), resource_holder::get(), allocated)
0681 {
0682 }
0683
0684 void assign(unique_resource_data&& that, std::true_type)
0685 noexcept(std::is_nothrow_assignable< internal_resource_type&, typename detail::move_or_copy_assign_ref< resource_type >::type >::value)
0686 {
0687 get_internal_resource() = static_cast< typename detail::move_or_copy_assign_ref< resource_type >::type >(that.get_resource());
0688 get_internal_deleter() = static_cast< typename detail::move_or_copy_assign_ref< deleter_type >::type >(that.get_deleter());
0689
0690 that.set_unallocated();
0691 }
0692
0693 void assign(unique_resource_data&& that, std::false_type)
0694 {
0695 get_internal_deleter() = static_cast< typename detail::move_or_copy_assign_ref< deleter_type >::type >(that.get_deleter());
0696 get_internal_resource() = static_cast< typename detail::move_or_copy_assign_ref< resource_type >::type >(that.get_resource());
0697
0698 that.set_unallocated();
0699 }
0700
0701 void swap_impl(unique_resource_data& that, std::true_type, std::true_type) noexcept
0702 {
0703 boost::core::invoke_swap(get_internal_resource(), that.get_internal_resource());
0704 boost::core::invoke_swap(get_internal_deleter(), that.get_internal_deleter());
0705 }
0706
0707 void swap_impl(unique_resource_data& that, std::true_type, std::false_type)
0708 {
0709 boost::core::invoke_swap(get_internal_deleter(), that.get_internal_deleter());
0710 boost::core::invoke_swap(get_internal_resource(), that.get_internal_resource());
0711 }
0712
0713 void swap_impl(unique_resource_data& that, std::false_type, std::false_type)
0714 {
0715 boost::core::invoke_swap(get_internal_resource(), that.get_internal_resource());
0716 boost::core::invoke_swap(get_internal_deleter(), that.get_internal_deleter());
0717 }
0718 };
0719
0720 template< typename Resource, typename Deleter >
0721 class unique_resource_data< Resource, Deleter, void > :
0722 public detail::resource_holder< Resource, use_resource_compact_storage< Resource, Deleter >::value >,
0723 public detail::deleter_holder< Resource, Deleter >
0724 {
0725 public:
0726 using resource_type = Resource;
0727 using deleter_type = Deleter;
0728 using traits_type = void;
0729
0730 private:
0731 using resource_holder = detail::resource_holder< resource_type, use_resource_compact_storage< resource_type, deleter_type >::value >;
0732 using deleter_holder = detail::deleter_holder< resource_type, deleter_type >;
0733
0734 public:
0735 using internal_resource_type = typename resource_holder::internal_resource_type;
0736 using internal_deleter_type = typename deleter_holder::internal_deleter_type;
0737
0738 private:
0739 bool m_allocated;
0740
0741 public:
0742 template<
0743 bool Requires = detail::conjunction< std::is_default_constructible< resource_holder >, std::is_default_constructible< deleter_holder > >::value,
0744 typename = typename std::enable_if< Requires >::type
0745 >
0746 constexpr unique_resource_data()
0747 noexcept(detail::conjunction< std::is_nothrow_default_constructible< resource_holder >, std::is_nothrow_default_constructible< deleter_holder > >::value) :
0748 resource_holder(),
0749 deleter_holder(),
0750 m_allocated(false)
0751 {
0752 }
0753
0754 unique_resource_data(unique_resource_data const&) = delete;
0755 unique_resource_data& operator= (unique_resource_data const&) = delete;
0756
0757 template<
0758 bool Requires = detail::conjunction<
0759 std::is_constructible< internal_resource_type, typename detail::move_or_copy_construct_ref< resource_type >::type >,
0760 std::is_constructible< internal_deleter_type, typename detail::move_or_copy_construct_ref< deleter_type >::type >
0761 >::value,
0762 typename = typename std::enable_if< Requires >::type
0763 >
0764 unique_resource_data(unique_resource_data&& that)
0765 noexcept(detail::conjunction<
0766 std::is_nothrow_constructible< internal_resource_type, typename detail::move_or_copy_construct_ref< resource_type >::type >,
0767 std::is_nothrow_constructible< internal_deleter_type, typename detail::move_or_copy_construct_ref< deleter_type >::type >
0768 >::value) :
0769 unique_resource_data
0770 (
0771 static_cast< unique_resource_data&& >(that),
0772 typename std::is_nothrow_constructible< internal_resource_type, typename detail::move_or_copy_construct_ref< resource_type >::type >::type(),
0773 typename std::is_nothrow_constructible< internal_deleter_type, typename detail::move_or_copy_construct_ref< deleter_type >::type >::type()
0774 )
0775 {
0776 }
0777
0778 template<
0779 typename D,
0780 typename = typename std::enable_if< detail::conjunction<
0781 std::is_default_constructible< resource_holder >,
0782 std::is_constructible< deleter_holder, D >
0783 >::value >::type
0784 >
0785 explicit unique_resource_data(default_resource_t, D&& del)
0786 noexcept(detail::conjunction<
0787 std::is_nothrow_default_constructible< resource_holder >,
0788 std::is_nothrow_constructible< deleter_holder, D >
0789 >::value) :
0790 resource_holder(),
0791 deleter_holder(static_cast< D&& >(del)),
0792 m_allocated(false)
0793 {
0794 }
0795
0796 template<
0797 typename R,
0798 typename D,
0799 typename = typename std::enable_if< detail::conjunction<
0800 detail::negation< detail::is_default_resource< R > >,
0801 std::is_constructible< resource_holder, R, D, bool >,
0802 std::is_constructible< deleter_holder, D, resource_type&, bool >
0803 >::value >::type
0804 >
0805 explicit unique_resource_data(R&& res, D&& del)
0806 noexcept(detail::conjunction<
0807 std::is_nothrow_constructible< resource_holder, R, D, bool >,
0808 std::is_nothrow_constructible< deleter_holder, D, resource_type&, bool >
0809 >::value) :
0810 resource_holder(static_cast< R&& >(res), static_cast< D&& >(del), true),
0811 deleter_holder(static_cast< D&& >(del), resource_holder::get(), true),
0812 m_allocated(true)
0813 {
0814 }
0815
0816 template<
0817 bool Requires = detail::conjunction<
0818 std::is_assignable< internal_resource_type&, typename detail::move_or_copy_assign_ref< resource_type >::type >,
0819 std::is_assignable< internal_deleter_type&, typename detail::move_or_copy_assign_ref< deleter_type >::type >
0820 >::value
0821 >
0822 typename std::enable_if< Requires, unique_resource_data& >::type operator= (unique_resource_data&& that)
0823 noexcept(detail::conjunction<
0824 std::is_nothrow_assignable< internal_resource_type&, typename detail::move_or_copy_assign_ref< resource_type >::type >,
0825 std::is_nothrow_assignable< internal_deleter_type&, typename detail::move_or_copy_assign_ref< deleter_type >::type >
0826 >::value)
0827 {
0828 assign(static_cast< unique_resource_data&& >(that), typename std::is_nothrow_move_assignable< internal_deleter_type >::type());
0829 return *this;
0830 }
0831
0832 resource_type& get_resource() noexcept
0833 {
0834 return resource_holder::get();
0835 }
0836
0837 resource_type const& get_resource() const noexcept
0838 {
0839 return resource_holder::get();
0840 }
0841
0842 internal_resource_type& get_internal_resource() noexcept
0843 {
0844 return resource_holder::get_internal();
0845 }
0846
0847 internal_resource_type const& get_internal_resource() const noexcept
0848 {
0849 return resource_holder::get_internal();
0850 }
0851
0852 deleter_type& get_deleter() noexcept
0853 {
0854 return deleter_holder::get();
0855 }
0856
0857 deleter_type const& get_deleter() const noexcept
0858 {
0859 return deleter_holder::get();
0860 }
0861
0862 internal_deleter_type& get_internal_deleter() noexcept
0863 {
0864 return deleter_holder::get_internal();
0865 }
0866
0867 internal_deleter_type const& get_internal_deleter() const noexcept
0868 {
0869 return deleter_holder::get_internal();
0870 }
0871
0872 bool is_allocated() const noexcept
0873 {
0874 return m_allocated;
0875 }
0876
0877 void set_unallocated() noexcept
0878 {
0879 m_allocated = false;
0880 }
0881
0882 template< typename R >
0883 void assign_resource(R&& res) noexcept(std::is_nothrow_assignable< internal_resource_type&, R >::value)
0884 {
0885 get_internal_resource() = static_cast< R&& >(res);
0886 m_allocated = true;
0887 }
0888
0889 template<
0890 bool Requires = detail::conjunction<
0891 detail::is_swappable< internal_resource_type >,
0892 detail::is_swappable< internal_deleter_type >,
0893 detail::disjunction<
0894 detail::is_nothrow_swappable< internal_resource_type >,
0895 detail::is_nothrow_swappable< internal_deleter_type >
0896 >
0897 >::value
0898 >
0899 typename std::enable_if< Requires >::type swap(unique_resource_data& that)
0900 noexcept(detail::conjunction< detail::is_nothrow_swappable< internal_resource_type >, detail::is_nothrow_swappable< internal_deleter_type > >::value)
0901 {
0902 swap_impl
0903 (
0904 that,
0905 std::integral_constant< bool, detail::is_nothrow_swappable< internal_resource_type >::value >(),
0906 std::integral_constant< bool, detail::conjunction<
0907 detail::is_nothrow_swappable< internal_resource_type >,
0908 detail::is_nothrow_swappable< internal_deleter_type >
0909 >::value >()
0910 );
0911 }
0912
0913 private:
0914 unique_resource_data(unique_resource_data&& that, std::true_type, std::true_type) noexcept :
0915 resource_holder(static_cast< typename detail::move_or_copy_construct_ref< resource_type >::type >(that.get_resource())),
0916 deleter_holder(static_cast< typename detail::move_or_copy_construct_ref< deleter_type >::type >(that.get_deleter())),
0917 m_allocated(that.m_allocated)
0918 {
0919 that.m_allocated = false;
0920 }
0921
0922 unique_resource_data(unique_resource_data&& that, std::false_type, std::true_type) :
0923 resource_holder(static_cast< resource_type const& >(that.get_resource())),
0924 deleter_holder(static_cast< typename detail::move_or_copy_construct_ref< deleter_type >::type >(that.get_deleter())),
0925 m_allocated(that.m_allocated)
0926 {
0927 that.m_allocated = false;
0928 }
0929
0930 unique_resource_data(unique_resource_data&& that, std::true_type, std::false_type) try :
0931 resource_holder(static_cast< typename detail::move_or_copy_construct_ref< resource_type >::type >(that.get_resource())),
0932 deleter_holder(static_cast< deleter_type const& >(that.get_deleter())),
0933 m_allocated(that.m_allocated)
0934 {
0935 that.m_allocated = false;
0936 }
0937 catch (...)
0938 {
0939
0940
0941 that.resource_holder::move_from(static_cast< internal_resource_type&& >(resource_holder::get_internal()));
0942 }
0943
0944 unique_resource_data(unique_resource_data&& that, std::false_type, std::false_type) :
0945 resource_holder(static_cast< resource_type const& >(that.get_resource())),
0946 deleter_holder(static_cast< deleter_type const& >(that.get_deleter())),
0947 m_allocated(that.m_allocated)
0948 {
0949 that.m_allocated = false;
0950 }
0951
0952 void assign(unique_resource_data&& that, std::true_type)
0953 noexcept(std::is_nothrow_assignable< internal_resource_type&, typename detail::move_or_copy_assign_ref< resource_type >::type >::value)
0954 {
0955 get_internal_resource() = static_cast< typename detail::move_or_copy_assign_ref< resource_type >::type >(that.get_resource());
0956 get_internal_deleter() = static_cast< typename detail::move_or_copy_assign_ref< deleter_type >::type >(that.get_deleter());
0957
0958 m_allocated = that.m_allocated;
0959 that.m_allocated = false;
0960 }
0961
0962 void assign(unique_resource_data&& that, std::false_type)
0963 {
0964 get_internal_deleter() = static_cast< typename detail::move_or_copy_assign_ref< deleter_type >::type >(that.get_deleter());
0965 get_internal_resource() = static_cast< typename detail::move_or_copy_assign_ref< resource_type >::type >(that.get_resource());
0966
0967 m_allocated = that.m_allocated;
0968 that.m_allocated = false;
0969 }
0970
0971 void swap_impl(unique_resource_data& that, std::true_type, std::true_type) noexcept
0972 {
0973 boost::core::invoke_swap(get_internal_resource(), that.get_internal_resource());
0974 boost::core::invoke_swap(get_internal_deleter(), that.get_internal_deleter());
0975 boost::core::invoke_swap(m_allocated, that.m_allocated);
0976 }
0977
0978 void swap_impl(unique_resource_data& that, std::true_type, std::false_type)
0979 {
0980 boost::core::invoke_swap(get_internal_deleter(), that.get_internal_deleter());
0981 boost::core::invoke_swap(get_internal_resource(), that.get_internal_resource());
0982 boost::core::invoke_swap(m_allocated, that.m_allocated);
0983 }
0984
0985 void swap_impl(unique_resource_data& that, std::false_type, std::false_type)
0986 {
0987 boost::core::invoke_swap(get_internal_resource(), that.get_internal_resource());
0988 boost::core::invoke_swap(get_internal_deleter(), that.get_internal_deleter());
0989 boost::core::invoke_swap(m_allocated, that.m_allocated);
0990 }
0991 };
0992
0993 template< typename T >
0994 struct is_dereferenceable_impl
0995 {
0996 template< typename U, typename R = decltype(*std::declval< U const& >()) >
0997 static std::true_type _is_dereferenceable_check(int);
0998 template< typename U >
0999 static std::false_type _is_dereferenceable_check(...);
1000
1001 using type = decltype(is_dereferenceable_impl::_is_dereferenceable_check< T >(0));
1002 };
1003
1004 template< typename T >
1005 struct is_dereferenceable : public is_dereferenceable_impl< T >::type { };
1006 template< >
1007 struct is_dereferenceable< void* > : public std::false_type { };
1008 template< >
1009 struct is_dereferenceable< const void* > : public std::false_type { };
1010 template< >
1011 struct is_dereferenceable< volatile void* > : public std::false_type { };
1012 template< >
1013 struct is_dereferenceable< const volatile void* > : public std::false_type { };
1014 template< >
1015 struct is_dereferenceable< void*& > : public std::false_type { };
1016 template< >
1017 struct is_dereferenceable< const void*& > : public std::false_type { };
1018 template< >
1019 struct is_dereferenceable< volatile void*& > : public std::false_type { };
1020 template< >
1021 struct is_dereferenceable< const volatile void*& > : public std::false_type { };
1022 template< >
1023 struct is_dereferenceable< void* const& > : public std::false_type { };
1024 template< >
1025 struct is_dereferenceable< const void* const& > : public std::false_type { };
1026 template< >
1027 struct is_dereferenceable< volatile void* const& > : public std::false_type { };
1028 template< >
1029 struct is_dereferenceable< const volatile void* const& > : public std::false_type { };
1030 template< >
1031 struct is_dereferenceable< void* volatile& > : public std::false_type { };
1032 template< >
1033 struct is_dereferenceable< const void* volatile& > : public std::false_type { };
1034 template< >
1035 struct is_dereferenceable< volatile void* volatile& > : public std::false_type { };
1036 template< >
1037 struct is_dereferenceable< const volatile void* volatile& > : public std::false_type { };
1038 template< >
1039 struct is_dereferenceable< void* const volatile& > : public std::false_type { };
1040 template< >
1041 struct is_dereferenceable< const void* const volatile& > : public std::false_type { };
1042 template< >
1043 struct is_dereferenceable< volatile void* const volatile& > : public std::false_type { };
1044 template< >
1045 struct is_dereferenceable< const volatile void* const volatile& > : public std::false_type { };
1046
1047 template< typename T, bool = detail::is_dereferenceable< T >::value >
1048 struct dereference_traits { };
1049 template< typename T >
1050 struct dereference_traits< T, true >
1051 {
1052 using result_type = decltype(*std::declval< T const& >());
1053 static constexpr bool is_noexcept = noexcept(*std::declval< T const& >());
1054 };
1055
1056 }
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112 template< typename Resource, typename Deleter, typename Traits BOOST_SCOPE_DETAIL_DOC(= void) >
1113 class unique_resource
1114 {
1115 public:
1116
1117 using resource_type = Resource;
1118
1119 using deleter_type = Deleter;
1120
1121 using traits_type = Traits;
1122
1123
1124 private:
1125 using data = detail::unique_resource_data< resource_type, deleter_type, traits_type >;
1126 using internal_resource_type = typename data::internal_resource_type;
1127 using internal_deleter_type = typename data::internal_deleter_type;
1128
1129 data m_data;
1130
1131
1132 public:
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147 template<
1148 bool Requires = std::is_default_constructible< data >::value,
1149 typename = typename std::enable_if< Requires >::type
1150 >
1151
1152 constexpr unique_resource() noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(std::is_nothrow_default_constructible< data >::value))
1153 {
1154 }
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172 template<
1173 typename D
1174
1175 , typename = typename std::enable_if<
1176 std::is_constructible< data, default_resource_t, typename detail::move_or_copy_construct_ref< D, deleter_type >::type >::value
1177 >::type
1178
1179 >
1180 unique_resource(default_resource_t res, D&& del)
1181 noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(
1182 std::is_nothrow_constructible<
1183 data,
1184 default_resource_t,
1185 typename detail::move_or_copy_construct_ref< D, deleter_type >::type
1186 >::value
1187 )) :
1188 m_data
1189 (
1190 res,
1191 static_cast< typename detail::move_or_copy_construct_ref< D, deleter_type >::type >(del)
1192 )
1193 {
1194 }
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209 template<
1210 typename R
1211
1212 , typename = typename std::enable_if< detail::conjunction<
1213 detail::is_nothrow_nonnull_default_constructible< deleter_type >,
1214 std::is_constructible< data, typename detail::move_or_copy_construct_ref< R, resource_type >::type, typename detail::move_or_copy_construct_ref< deleter_type >::type >,
1215 detail::disjunction< detail::negation< std::is_reference< resource_type > >, std::is_reference< R > >
1216 >::value >::type
1217
1218 >
1219 explicit unique_resource(R&& res)
1220 noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(
1221 std::is_nothrow_constructible<
1222 data,
1223 typename detail::move_or_copy_construct_ref< R, resource_type >::type,
1224 typename detail::move_or_copy_construct_ref< deleter_type >::type
1225 >::value
1226 )) :
1227 m_data
1228 (
1229 static_cast< typename detail::move_or_copy_construct_ref< R, resource_type >::type >(res),
1230 static_cast< typename detail::move_or_copy_construct_ref< deleter_type >::type >(deleter_type())
1231 )
1232 {
1233 }
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257 template<
1258 typename R,
1259 typename D
1260
1261 , typename = typename std::enable_if< detail::conjunction<
1262 std::is_constructible< data, typename detail::move_or_copy_construct_ref< R, resource_type >::type, typename detail::move_or_copy_construct_ref< D, deleter_type >::type >,
1263 detail::disjunction< detail::negation< std::is_reference< resource_type > >, std::is_reference< R > >
1264 >::value >::type
1265
1266 >
1267 unique_resource(R&& res, D&& del)
1268 noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(
1269 std::is_nothrow_constructible<
1270 data,
1271 typename detail::move_or_copy_construct_ref< R, resource_type >::type,
1272 typename detail::move_or_copy_construct_ref< D, deleter_type >::type
1273 >::value
1274 )) :
1275 m_data
1276 (
1277 static_cast< typename detail::move_or_copy_construct_ref< R, resource_type >::type >(res),
1278 static_cast< typename detail::move_or_copy_construct_ref< D, deleter_type >::type >(del)
1279 )
1280 {
1281 }
1282
1283 unique_resource(unique_resource const&) = delete;
1284 unique_resource& operator= (unique_resource const&) = delete;
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308 template<
1309 bool Requires = std::is_move_constructible< data >::value,
1310 typename = typename std::enable_if< Requires >::type
1311 >
1312
1313 unique_resource(unique_resource&& that) noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(std::is_nothrow_move_constructible< data >::value)) :
1314 m_data(static_cast< data&& >(that.m_data))
1315 {
1316 }
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339 #if !defined(BOOST_SCOPE_DOXYGEN)
1340 template< bool Requires = std::is_move_assignable< data >::value >
1341 typename std::enable_if< Requires, unique_resource& >::type
1342 #else
1343 unique_resource&
1344 #endif
1345 operator= (unique_resource&& that)
1346 noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(std::is_nothrow_move_assignable< data >::value))
1347 {
1348 reset();
1349 m_data = static_cast< data&& >(that.m_data);
1350 return *this;
1351 }
1352
1353
1354
1355
1356
1357
1358 ~unique_resource() noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(detail::is_nothrow_invocable< deleter_type&, resource_type& >::value))
1359 {
1360 if (BOOST_LIKELY(m_data.is_allocated()))
1361 m_data.get_deleter()(m_data.get_resource());
1362 }
1363
1364
1365
1366
1367
1368
1369
1370
1371 explicit operator bool () const noexcept
1372 {
1373 return m_data.is_allocated();
1374 }
1375
1376
1377
1378
1379
1380
1381 bool allocated() const noexcept
1382 {
1383 return m_data.is_allocated();
1384 }
1385
1386
1387
1388
1389
1390
1391 resource_type const& get() const noexcept
1392 {
1393 return m_data.get_resource();
1394 }
1395
1396
1397
1398
1399
1400
1401 deleter_type const& get_deleter() const noexcept
1402 {
1403 return m_data.get_deleter();
1404 }
1405
1406
1407
1408
1409
1410
1411
1412
1413 void release() noexcept
1414 {
1415 m_data.set_unallocated();
1416 }
1417
1418
1419
1420
1421
1422
1423
1424
1425 void reset() noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(detail::is_nothrow_invocable< deleter_type&, resource_type& >::value))
1426 {
1427 if (BOOST_LIKELY(m_data.is_allocated()))
1428 {
1429 m_data.get_deleter()(m_data.get_resource());
1430 m_data.set_unallocated();
1431 }
1432 }
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450 template< typename R >
1451 #if !defined(BOOST_SCOPE_DOXYGEN)
1452 typename std::enable_if< detail::conjunction<
1453 std::is_assignable< internal_resource_type&, typename detail::move_or_copy_assign_ref< R, resource_type >::type >,
1454 detail::disjunction< detail::negation< std::is_reference< resource_type > >, std::is_reference< R > >
1455 >::value >::type
1456 #else
1457 void
1458 #endif
1459 reset(R&& res)
1460 noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(
1461 detail::conjunction<
1462 detail::is_nothrow_invocable< deleter_type&, resource_type& >,
1463 std::is_nothrow_assignable< internal_resource_type&, typename detail::move_or_copy_assign_ref< R, resource_type >::type >
1464 >::value
1465 ))
1466 {
1467 reset_impl
1468 (
1469 static_cast< R&& >(res),
1470 typename detail::conjunction<
1471 detail::is_nothrow_invocable< deleter_type&, resource_type& >,
1472 std::is_nothrow_assignable< internal_resource_type&, typename detail::move_or_copy_assign_ref< R, resource_type >::type >
1473 >::type()
1474 );
1475 }
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490 #if !defined(BOOST_SCOPE_DOXYGEN)
1491 template< bool Requires = detail::is_dereferenceable< resource_type >::value >
1492 typename std::enable_if< Requires, resource_type const& >::type
1493 #else
1494 resource_type const&
1495 #endif
1496 operator-> () const noexcept
1497 {
1498 return get();
1499 }
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510 #if !defined(BOOST_SCOPE_DOXYGEN)
1511 template< bool Requires = detail::is_dereferenceable< resource_type >::value >
1512 typename detail::dereference_traits< resource_type, Requires >::result_type
1513 #else
1514 auto
1515 #endif
1516 operator* () const
1517 noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(detail::dereference_traits< resource_type, Requires >::is_noexcept))
1518 {
1519 return *get();
1520 }
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539 #if !defined(BOOST_SCOPE_DOXYGEN)
1540 template< bool Requires = detail::is_swappable< data >::value >
1541 typename std::enable_if< Requires >::type
1542 #else
1543 void
1544 #endif
1545 swap(unique_resource& that)
1546 noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(detail::is_nothrow_swappable< data >::value))
1547 {
1548 m_data.swap(that.m_data);
1549 }
1550
1551
1552
1553
1554
1555
1556 #if !defined(BOOST_SCOPE_DOXYGEN)
1557 template< bool Requires = detail::is_swappable< data >::value >
1558 friend typename std::enable_if< Requires >::type
1559 #else
1560 friend void
1561 #endif
1562 swap(unique_resource& left, unique_resource& right)
1563 noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(detail::is_nothrow_swappable< data >::value))
1564 {
1565 left.swap(right);
1566 }
1567
1568
1569 private:
1570
1571 template< typename R >
1572 void reset_impl(R&& res, std::true_type) noexcept
1573 {
1574 reset();
1575 m_data.assign_resource(static_cast< typename detail::move_or_copy_assign_ref< R, resource_type >::type >(res));
1576 }
1577
1578
1579 template< typename R >
1580 void reset_impl(R&& res, std::false_type)
1581 {
1582 try
1583 {
1584 reset();
1585 m_data.assign_resource(static_cast< typename detail::move_or_copy_assign_ref< R, resource_type >::type >(res));
1586 }
1587 catch (...)
1588 {
1589 m_data.get_deleter()(static_cast< R&& >(res));
1590 throw;
1591 }
1592 }
1593
1594 };
1595
1596 #if !defined(BOOST_NO_CXX17_DEDUCTION_GUIDES)
1597 template<
1598 typename Resource,
1599 typename Deleter,
1600 typename = typename std::enable_if< !detail::is_default_resource< Resource >::value >::type
1601 >
1602 unique_resource(Resource, Deleter) -> unique_resource< Resource, Deleter >;
1603 #endif
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620 template< typename Resource, typename Deleter, typename Invalid >
1621 inline unique_resource< typename std::decay< Resource >::type, typename std::decay< Deleter >::type >
1622 make_unique_resource_checked(Resource&& res, Invalid const& invalid, Deleter&& del)
1623 noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(
1624 detail::conjunction<
1625 std::is_nothrow_constructible< typename std::decay< Resource >::type, typename detail::move_or_copy_construct_ref< Resource, typename std::decay< Resource >::type >::type >,
1626 std::is_nothrow_constructible< typename std::decay< Deleter >::type, typename detail::move_or_copy_construct_ref< Deleter, typename std::decay< Deleter >::type >::type >
1627 >::value
1628 ))
1629 {
1630 using unique_resource_type = unique_resource< typename std::decay< Resource >::type, typename std::decay< Deleter >::type >;
1631 if (!(res == invalid))
1632 return unique_resource_type(static_cast< Resource&& >(res), static_cast< Deleter&& >(del));
1633 else
1634 return unique_resource_type(default_resource_t(), static_cast< Deleter&& >(del));
1635 }
1636
1637 }
1638 }
1639
1640 #include <boost/scope/detail/footer.hpp>
1641
1642 #endif