cycle_ptr
cycle_ptr.h
1 #ifndef CYCLE_PTR_CYCLE_PTR_H
2 #define CYCLE_PTR_CYCLE_PTR_H
3 
4 #include <cassert>
5 #include <cstddef>
6 #include <memory>
7 #include <tuple>
8 #include <type_traits>
9 #include <utility>
10 #include <iosfwd>
11 #include <cycle_ptr/detail/intrusive_ptr.h>
12 #include <cycle_ptr/detail/control.h>
13 #include <cycle_ptr/detail/vertex.h>
14 
15 namespace cycle_ptr {
16 
17 
24 struct unowned_cycle_t {};
25 
30 inline constexpr auto unowned_cycle = unowned_cycle_t();
31 
32 template<typename> class cycle_member_ptr;
33 template<typename> class cycle_gptr;
34 template<typename> class cycle_weak_ptr;
35 template<typename> class cycle_allocator;
36 
37 template<typename T, typename Alloc, typename... Args>
38 auto allocate_cycle(Alloc alloc, Args&&... args) -> cycle_gptr<T>;
39 
49 class cycle_base {
50  template<typename> friend class cycle_member_ptr;
51  template<typename> friend class cycle_allocator;
52 
53  protected:
63  : control_(detail::base_control::publisher_lookup(this, sizeof(*this)))
64  {}
65 
71  cycle_base([[maybe_unused]] unowned_cycle_t unowned_tag)
72  : control_(detail::base_control::unowned_control())
73  {}
74 
86  noexcept
87  : cycle_base()
88  {}
89 
95  auto operator=(const cycle_base&)
96  noexcept
97  -> cycle_base& {
98  return *this;
99  }
100 
102  ~cycle_base() noexcept = default;
103 
118  template<typename T>
119  auto shared_from_this(T* this_ptr) const
120  -> cycle_gptr<T> {
121  assert(control_ != nullptr);
122 
123  // Protect against leaking out this from inside constructors.
124  // This mimics std::shared_ptr, where shared_from_this() is not
125  // valid until after the construction completes.
126  [[unlikely]]
127  if (control_->under_construction)
128  throw std::bad_weak_ptr();
129 
130  cycle_gptr<T> result;
131  if (!control_->weak_acquire()) throw std::bad_weak_ptr();
132  result.emplace_(this_ptr, control_);
133  return result;
134  }
135 
136  private:
139 };
140 
150 template<typename T>
151 class cycle_member_ptr
152 : private detail::vertex
153 {
154  template<typename> friend class cycle_member_ptr;
155  template<typename> friend class cycle_gptr;
156  template<typename> friend class cycle_weak_ptr;
157 
158  public:
160  using element_type = std::remove_extent_t<T>;
163 
198  explicit cycle_member_ptr([[maybe_unused]] unowned_cycle_t unowned_tag) noexcept
200  {}
201 
237  cycle_member_ptr(unowned_cycle_t unowned_tag, [[maybe_unused]] std::nullptr_t nil) noexcept
238  : cycle_member_ptr(unowned_tag)
239  {}
240 
276  template<typename U, typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
277  cycle_member_ptr([[maybe_unused]] unowned_cycle_t unowned_tag, const cycle_member_ptr<U>& ptr)
278  : detail::vertex(detail::base_control::unowned_control()),
279  target_(ptr.target_)
280  {
281  ptr.throw_if_owner_expired();
282  this->detail::vertex::reset(ptr.get_control(), false, false);
283  }
284 
323  template<typename U, typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
325  : cycle_member_ptr(unowned_tag, ptr)
326  {
327  ptr.reset();
328  }
329 
365  template<typename U, typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
366  cycle_member_ptr([[maybe_unused]] unowned_cycle_t unowned_tag, const cycle_gptr<U>& ptr)
367  : detail::vertex(detail::base_control::unowned_control()),
368  target_(ptr.target_)
369  {
370  this->detail::vertex::reset(ptr.target_ctrl_, false, true);
371  }
372 
411  template<typename U, typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
412  cycle_member_ptr([[maybe_unused]] unowned_cycle_t unowned_tag, cycle_gptr<U>&& ptr)
413  : detail::vertex(detail::base_control::unowned_control()),
414  target_(std::exchange(ptr.target_, nullptr))
415  {
416  this->detail::vertex::reset(
417  std::move(ptr.target_ctrl_),
418  true, true);
419  }
420 
439  template<typename U>
440  cycle_member_ptr([[maybe_unused]] unowned_cycle_t unowned_tag, const cycle_member_ptr<U>& ptr, element_type* target)
441  : detail::vertex(detail::base_control::unowned_control()),
442  target_(target)
443  {
444  ptr.throw_if_owner_expired();
445  this->detail::vertex::reset(ptr.get_control(), false, false);
446  }
447 
464  template<typename U>
465  cycle_member_ptr([[maybe_unused]] unowned_cycle_t unowned_tag, const cycle_gptr<U>& ptr, element_type* target)
466  : detail::vertex(detail::base_control::unowned_control()),
467  target_(target)
468  {
469  this->detail::vertex::reset(ptr.target_ctrl_, false, true);
470  }
471 
508  template<typename U, typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
510  : cycle_member_ptr(unowned_tag, cycle_gptr<U>(ptr))
511  {}
512 
523  explicit cycle_member_ptr(cycle_base& owner) noexcept
524  : vertex(owner.control_)
525  {}
526 
538  cycle_member_ptr(cycle_base& owner, [[maybe_unused]] std::nullptr_t nil) noexcept
539  : cycle_member_ptr(owner)
540  {}
541 
553  template<typename U, typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
555  : detail::vertex(owner.control_),
556  target_(ptr.target_)
557  {
558  ptr.throw_if_owner_expired();
559  this->detail::vertex::reset(ptr.get_control(), false, false);
560  }
561 
576  template<typename U, typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
578  : cycle_member_ptr(owner, ptr)
579  {
580  ptr.reset();
581  }
582 
594  template<typename U, typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
596  : detail::vertex(owner.control_),
597  target_(ptr.target_)
598  {
599  this->detail::vertex::reset(ptr.target_ctrl_, false, true);
600  }
601 
616  template<typename U, typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
618  : detail::vertex(owner.control_),
619  target_(std::exchange(ptr.target_, nullptr))
620  {
621  this->detail::vertex::reset(
622  std::move(ptr.target_ctrl_),
623  true, true);
624  }
625 
646  template<typename U>
648  : detail::vertex(owner.control_),
649  target_(target)
650  {
651  ptr.throw_if_owner_expired();
652  this->detail::vertex::reset(ptr.get_control(), false, false);
653  }
654 
675  template<typename U>
677  : detail::vertex(owner.control_),
678  target_(target)
679  {
680  this->detail::vertex::reset(ptr.target_ctrl_, false, true);
681  }
682 
693  template<typename U, typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
695  : cycle_member_ptr(owner, cycle_gptr<U>(ptr))
696  {}
697 
717 
736  cycle_member_ptr([[maybe_unused]] std::nullptr_t nil) {}
737 
757  : target_(ptr.target_)
758  {
759  ptr.throw_if_owner_expired();
760  this->detail::vertex::reset(ptr.get_control(), false, false);
761  }
762 
785  : cycle_member_ptr(ptr)
786  {
787  ptr.reset();
788  }
789 
808  template<typename U, typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
810  : target_(ptr.target_)
811  {
812  ptr.throw_if_owner_expired();
813  this->detail::vertex::reset(ptr.get_control(), false, false);
814  }
815 
837  template<typename U, typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
839  : cycle_member_ptr(ptr)
840  {
841  ptr.reset();
842  }
843 
862  template<typename U, typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
864  : target_(ptr.target_)
865  {
866  this->detail::vertex::reset(ptr.target_ctrl_, false, true);
867  }
868 
890  template<typename U, typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
892  : target_(std::exchange(ptr.target_, nullptr))
893  {
894  this->detail::vertex::reset(
895  std::move(ptr.target_ctrl_),
896  true, true);
897  }
898 
920  template<typename U>
922  : target_(target)
923  {
924  ptr.throw_if_owner_expired();
925  this->detail::vertex::reset(ptr.get_control(), false, false);
926  }
927 
949  template<typename U>
951  : target_(target)
952  {
953  this->detail::vertex::reset(ptr.target_ctrl_, false, true);
954  }
955 
974  template<typename U, typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
975  explicit cycle_member_ptr(const cycle_weak_ptr<U>& ptr)
976  : cycle_member_ptr(cycle_gptr<U>(ptr))
977  {}
978 
986  auto operator=([[maybe_unused]] std::nullptr_t nil)
987  -> cycle_member_ptr& {
988  reset();
989  return *this;
990  }
991 
1000  auto operator=(const cycle_member_ptr& other)
1001  -> cycle_member_ptr& {
1002  other.throw_if_owner_expired();
1003 
1004  this->detail::vertex::reset(other.get_control(), false, false);
1005  target_ = other.target_;
1006  return *this;
1007  }
1008 
1021  -> cycle_member_ptr& {
1022  if (this != &other) [[likely]] {
1023  *this = other;
1024  other.reset();
1025  }
1026  return *this;
1027  }
1028 
1037  template<typename U, typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
1038  auto operator=(const cycle_member_ptr<U>& other)
1039  -> cycle_member_ptr& {
1040  other.throw_if_owner_expired();
1041 
1042  this->detail::vertex::reset(other.get_control(), false, false);
1043  target_ = other.target_;
1044  return *this;
1045  }
1046 
1058  template<typename U, typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
1060  -> cycle_member_ptr& {
1061  *this = other;
1062  other.reset();
1063  return *this;
1064  }
1065 
1073  template<typename U, typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
1074  auto operator=(const cycle_gptr<U>& other)
1075  -> cycle_member_ptr& {
1076  this->detail::vertex::reset(other.target_ctrl_, false, true);
1077  target_ = other.target_;
1078  return *this;
1079  }
1080 
1091  template<typename U, typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
1092  auto operator=(cycle_gptr<U>&& other)
1093  -> cycle_member_ptr& {
1094  this->detail::vertex::reset(
1095  std::move(other.target_ctrl_),
1096  true, true);
1097  target_ = std::exchange(other.target_, nullptr);
1098  return *this;
1099  }
1100 
1108  auto reset()
1109  -> void {
1110  this->detail::vertex::reset();
1111  target_ = nullptr;
1112  }
1113 
1123  auto swap(cycle_member_ptr& other)
1124  -> void {
1125  std::tie(*this, other) = std::forward_as_tuple(
1126  cycle_gptr<T>(std::move(other)),
1127  cycle_gptr<T>(std::move(*this)));
1128  }
1129 
1139  auto swap(cycle_gptr<T>& other)
1140  -> void {
1141  std::tie(*this, other) = std::forward_as_tuple(
1142  cycle_gptr<T>(std::move(other)),
1143  cycle_gptr<T>(std::move(*this)));
1144  }
1145 
1150  auto get() const
1151  -> T* {
1153  return target_;
1154  }
1155 
1162  template<bool Enable = !std::is_void_v<T>>
1163  auto operator*() const
1164  -> std::enable_if_t<Enable, T>& {
1165  assert(get() != nullptr);
1166  return *get();
1167  }
1168 
1175  template<bool Enable = !std::is_void_v<T>>
1176  auto operator->() const
1177  -> std::enable_if_t<Enable, T>* {
1178  assert(get() != nullptr);
1179  return get();
1180  }
1181 
1187  explicit operator bool() const {
1188  return get() != nullptr;
1189  }
1190 
1192  template<typename U>
1193  auto owner_before(const cycle_weak_ptr<U>& other) const
1194  noexcept
1195  -> bool {
1196  return get_control() < other.target_ctrl_;
1197  }
1198 
1200  template<typename U>
1201  auto owner_before(const cycle_gptr<U>& other) const
1202  noexcept
1203  -> bool {
1204  return get_control() < other.target_ctrl_;
1205  }
1206 
1208  template<typename U>
1209  auto owner_before(const cycle_member_ptr<U>& other) const
1210  noexcept
1211  -> bool {
1212  return get_control() < other.get_control();
1213  }
1214 
1215  private:
1217  T* target_ = nullptr;
1218 };
1219 
1231 template<typename T>
1232 class cycle_gptr {
1233  template<typename> friend class cycle_member_ptr;
1234  template<typename> friend class cycle_gptr;
1235  template<typename> friend class cycle_weak_ptr;
1236  friend class cycle_base;
1237 
1238  template<typename Type, typename Alloc, typename... Args>
1239  friend auto cycle_ptr::allocate_cycle(Alloc alloc, Args&&... args) -> cycle_gptr<Type>;
1240 
1241  public:
1243  using element_type = std::remove_extent_t<T>;
1246 
1249  constexpr cycle_gptr() noexcept {}
1250 
1253  constexpr cycle_gptr([[maybe_unused]] std::nullptr_t nil) noexcept
1254  : cycle_gptr()
1255  {}
1256 
1262  cycle_gptr(const cycle_gptr& other) noexcept
1263  : target_(other.target_),
1264  target_ctrl_(other.target_ctrl_)
1265  {
1266  if (target_ctrl_ != nullptr) target_ctrl_->acquire_no_red();
1267  }
1268 
1277  cycle_gptr(cycle_gptr&& other) noexcept
1278  : target_(std::exchange(other.target_, nullptr)),
1279  target_ctrl_(other.target_ctrl_.detach(), false)
1280  {}
1281 
1287  template<typename U, typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
1288  cycle_gptr(const cycle_gptr<U>& other) noexcept
1289  : target_(other.target_),
1290  target_ctrl_(other.target_ctrl_)
1291  {
1292  if (target_ctrl_ != nullptr) target_ctrl_->acquire_no_red();
1293  }
1294 
1303  template<typename U, typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
1304  cycle_gptr(cycle_gptr<U>&& other) noexcept
1305  : target_(std::exchange(other.target_, nullptr)),
1306  target_ctrl_(other.target_ctrl_.detach(), false)
1307  {}
1308 
1316  template<typename U, typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
1318  : target_(other.target_),
1319  target_ctrl_(other.get_control())
1320  {
1321  other.throw_if_owner_expired();
1322  if (target_ctrl_ != nullptr) target_ctrl_->acquire();
1323  }
1324 
1335  template<typename U, typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
1337  : cycle_gptr(other)
1338  {
1339  other.reset();
1340  }
1341 
1350  template<typename U>
1351  cycle_gptr(const cycle_gptr<U>& other, element_type* target) noexcept
1352  : target_(target),
1353  target_ctrl_(other.target_ctrl_)
1354  {
1355  if (target_ctrl_ != nullptr) target_ctrl_->acquire_no_red();
1356  }
1357 
1368  template<typename U>
1370  : target_(target),
1371  target_ctrl_(other.get_control())
1372  {
1373  other.throw_if_owner_expired();
1374  if (target_ctrl_ != nullptr) target_ctrl_->acquire();
1375  }
1376 
1384  template<typename U, typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
1385  explicit cycle_gptr(const cycle_weak_ptr<U>& other)
1386  : target_(other.target_),
1387  target_ctrl_(other.target_ctrl_)
1388  {
1389  if (target_ctrl_ == nullptr || !target_ctrl_->weak_acquire())
1390  throw std::bad_weak_ptr();
1391  }
1392 
1398  auto operator=(const cycle_gptr& other)
1399  noexcept
1400  -> cycle_gptr& {
1401  detail::intrusive_ptr<detail::base_control> bc = other.target_ctrl_;
1402  if (bc != nullptr) bc->acquire_no_red();
1403 
1404  target_ = other.target_;
1405  bc.swap(target_ctrl_);
1406  if (bc != nullptr) bc->release(bc == target_ctrl_);
1407 
1408  return *this;
1409  }
1410 
1419  auto operator=(cycle_gptr&& other)
1420  noexcept
1421  -> cycle_gptr& {
1422  auto bc = std::move(other.target_ctrl_);
1423 
1424  target_ = std::exchange(other.target_, nullptr);
1425  bc.swap(target_ctrl_);
1426  if (bc != nullptr) bc->release(bc == target_ctrl_);
1427 
1428  return *this;
1429  }
1430 
1436  template<typename U, typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
1437  auto operator=(const cycle_gptr<U>& other)
1438  noexcept
1439  -> cycle_gptr& {
1440  detail::intrusive_ptr<detail::base_control> bc = other.target_ctrl_;
1441  if (bc != nullptr) bc->acquire_no_red();
1442 
1443  target_ = other.target_;
1444  bc.swap(target_ctrl_);
1445  if (bc != nullptr) bc->release(bc == target_ctrl_);
1446 
1447  return *this;
1448  }
1449 
1458  template<typename U, typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
1459  auto operator=(cycle_gptr<U>&& other)
1460  noexcept
1461  -> cycle_gptr& {
1462  auto bc = std::move(other.target_ctrl_);
1463 
1464  target_ = std::exchange(other.target_, nullptr);
1465  bc.swap(target_ctrl_);
1466  if (bc != nullptr) bc->release(bc == target_ctrl_);
1467 
1468  return *this;
1469  }
1470 
1478  template<typename U, typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
1479  auto operator=(const cycle_member_ptr<U>& other)
1480  -> cycle_gptr& {
1481  other.throw_if_owner_expired();
1482 
1483  detail::intrusive_ptr<detail::base_control> bc = other.get_control();
1484  if (bc != nullptr) bc->acquire();
1485 
1486  target_ = other.target_;
1487  bc.swap(target_ctrl_);
1488  if (bc != nullptr) bc->release(bc == target_ctrl_);
1489 
1490  return *this;
1491  }
1492 
1503  template<typename U, typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
1505  -> cycle_gptr& {
1506  *this = other;
1507  other.reset();
1508  return *this;
1509  }
1510 
1511  ~cycle_gptr() noexcept {
1512  if (target_ctrl_ != nullptr)
1513  target_ctrl_->release();
1514  }
1515 
1521  auto reset()
1522  noexcept
1523  -> void {
1524  if (target_ctrl_ != nullptr) {
1525  target_ = nullptr;
1526  target_ctrl_->release();
1527  target_ctrl_.reset();
1528  }
1529  }
1530 
1539  auto swap(cycle_gptr& other)
1540  noexcept
1541  -> void {
1542  std::swap(target_, other.target_);
1543  target_ctrl_.swap(other.target_ctrl_);
1544  }
1545 
1557  -> void {
1558  other.swap(*this);
1559  }
1560 
1564  auto get() const
1565  noexcept
1566  -> T* {
1567  return target_;
1568  }
1569 
1574  template<bool Enable = !std::is_void_v<T>>
1575  auto operator*() const
1576  -> std::enable_if_t<Enable, T>& {
1577  assert(get() != nullptr);
1578  return *get();
1579  }
1580 
1585  template<bool Enable = !std::is_void_v<T>>
1586  auto operator->() const
1587  -> std::enable_if_t<Enable, T>* {
1588  assert(get() != nullptr);
1589  return get();
1590  }
1591 
1596  explicit operator bool() const noexcept {
1597  return get() != nullptr;
1598  }
1599 
1601  template<typename U>
1602  auto owner_before(const cycle_weak_ptr<U>& other) const
1603  noexcept
1604  -> bool {
1605  return target_ctrl_ < other.target_ctrl_;
1606  }
1607 
1609  template<typename U>
1610  auto owner_before(const cycle_gptr<U>& other) const
1611  noexcept
1612  -> bool {
1613  return target_ctrl_ < other.target_ctrl_;
1614  }
1615 
1617  template<typename U>
1618  auto owner_before(const cycle_member_ptr<U>& other) const
1619  noexcept
1620  -> bool {
1621  return target_ctrl_ < other.get_control();
1622  }
1623 
1624  private:
1645  auto emplace_(T* new_target, detail::intrusive_ptr<detail::base_control> new_target_ctrl)
1646  noexcept
1647  -> void {
1648  assert(new_target_ctrl == nullptr || new_target != nullptr);
1649  assert(target_ctrl_ == nullptr);
1650 
1651  target_ = new_target;
1652  target_ctrl_ = std::move(new_target_ctrl);
1653  }
1654 
1656  T* target_ = nullptr;
1658  detail::intrusive_ptr<detail::base_control> target_ctrl_ = nullptr;
1659 };
1660 
1661 
1669 template<typename T>
1670 class cycle_weak_ptr {
1671  template<typename> friend class cycle_member_ptr;
1672  template<typename> friend class cycle_gptr;
1673  template<typename> friend class cycle_weak_ptr;
1674 
1675  public:
1677  using element_type = std::remove_extent_t<T>;
1678 
1680  constexpr cycle_weak_ptr() noexcept {}
1681 
1683  cycle_weak_ptr(const cycle_weak_ptr& other) noexcept
1684  : target_(other.target_),
1685  target_ctrl_(other.target_ctrl_)
1686  {}
1687 
1693  cycle_weak_ptr(cycle_weak_ptr&& other) noexcept
1694  : target_(std::exchange(other.target_, nullptr)),
1695  target_ctrl_(other.target_ctrl_.detach(), false)
1696  {}
1697 
1699  template<typename U, typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
1700  cycle_weak_ptr(const cycle_weak_ptr<U>& other) noexcept
1701  : target_(other.target_),
1702  target_ctrl_(other.target_ctrl_)
1703  {}
1704 
1707  template<typename U, typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
1709  : target_(std::exchange(other.target_, nullptr)),
1710  target_ctrl_(other.target_ctrl_.detach(), false)
1711  {}
1712 
1715  template<typename U, typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
1716  cycle_weak_ptr(const cycle_gptr<U>& other) noexcept
1717  : target_(other.target_),
1718  target_ctrl_(other.target_ctrl_)
1719  {}
1720 
1723  template<typename U, typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
1724  cycle_weak_ptr(const cycle_member_ptr<U>& other) noexcept
1725  : target_(other.target_),
1726  target_ctrl_(other.get_control())
1727  {}
1728 
1730  auto operator=(const cycle_weak_ptr& other)
1731  noexcept
1732  -> cycle_weak_ptr& {
1733  target_ = other.target_;
1734  target_ctrl_ = other.target_ctrl_;
1735  return *this;
1736  }
1737 
1741  noexcept
1742  -> cycle_weak_ptr& {
1743  target_ = std::exchange(other.target_, nullptr);
1744  target_ctrl_.reset(other.target_ctrl_.detach(), false);
1745  return *this;
1746  }
1747 
1749  template<typename U, typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
1750  auto operator=(const cycle_weak_ptr<U>& other)
1751  noexcept
1752  -> cycle_weak_ptr& {
1753  target_ = other.target_;
1754  target_ctrl_ = other.target_ctrl_;
1755  return *this;
1756  }
1757 
1760  template<typename U, typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
1762  noexcept
1763  -> cycle_weak_ptr& {
1764  target_ = std::exchange(other.target_, nullptr);
1765  target_ctrl_.reset(other.target_ctrl_.detach(), false);
1766  return *this;
1767  }
1768 
1771  template<typename U, typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
1772  auto operator=(const cycle_gptr<U>& other)
1773  noexcept
1774  -> cycle_weak_ptr& {
1775  target_ = other.target_;
1776  target_ctrl_ = other.target_ctrl_;
1777  return *this;
1778  }
1779 
1782  template<typename U, typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
1783  auto operator=(const cycle_member_ptr<U>& other)
1784  noexcept
1785  -> cycle_weak_ptr& {
1786  target_ = other.target_;
1787  target_ctrl_ = other.get_control();
1788  return *this;
1789  }
1790 
1793  auto reset()
1794  noexcept
1795  -> void {
1796  target_ = nullptr;
1797  target_ctrl_.reset();
1798  }
1799 
1801  auto swap(cycle_weak_ptr& other)
1802  noexcept
1803  -> void {
1804  std::swap(target_, other.target_);
1805  target_ctrl_.swap(other.target_ctrl_);
1806  }
1807 
1810  auto expired() const
1811  noexcept
1812  -> bool {
1813  return target_ctrl_ == nullptr || target_ctrl_->expired();
1814  }
1815 
1822  auto lock() const
1823  noexcept
1824  -> cycle_gptr<T> {
1825  cycle_gptr<T> result;
1826  if (target_ctrl_ != nullptr && target_ctrl_->weak_acquire())
1827  result.emplace_(target_, target_ctrl_);
1828  return result;
1829  }
1830 
1832  template<typename U>
1833  auto owner_before(const cycle_weak_ptr<U>& other) const
1834  noexcept
1835  -> bool {
1836  return target_ctrl_ < other.target_ctrl_;
1837  }
1838 
1840  template<typename U>
1841  auto owner_before(const cycle_gptr<U>& other) const
1842  noexcept
1843  -> bool {
1844  return target_ctrl_ < other.target_ctrl_;
1845  }
1846 
1848  template<typename U>
1849  auto owner_before(const cycle_member_ptr<U>& other) const
1850  noexcept
1851  -> bool {
1852  return target_ctrl_ < other.get_control();
1853  }
1854 
1855  private:
1857  T* target_ = nullptr;
1859  detail::intrusive_ptr<detail::base_control> target_ctrl_ = nullptr;
1860 };
1861 
1862 
1865 template<typename T, typename U>
1866 inline auto operator==(const cycle_member_ptr<T>& x, const cycle_member_ptr<U>& y)
1867 noexcept
1868 -> bool {
1869  return x.get() == y.get();
1870 }
1871 
1874 template<typename T>
1875 inline auto operator==(const cycle_member_ptr<T>& x, [[maybe_unused]] std::nullptr_t y)
1876 noexcept
1877 -> bool {
1878  return !x;
1879 }
1880 
1883 template<typename U>
1884 inline auto operator==([[maybe_unused]] std::nullptr_t x, const cycle_member_ptr<U>& y)
1885 noexcept
1886 -> bool {
1887  return !y;
1888 }
1889 
1892 template<typename T, typename U>
1893 inline auto operator!=(const cycle_member_ptr<T>& x, const cycle_member_ptr<U>& y)
1894 noexcept
1895 -> bool {
1896  return !(x == y);
1897 }
1898 
1901 template<typename T>
1902 inline auto operator!=(const cycle_member_ptr<T>& x, [[maybe_unused]] std::nullptr_t y)
1903 noexcept
1904 -> bool {
1905  return bool(x);
1906 }
1907 
1910 template<typename U>
1911 inline auto operator!=([[maybe_unused]] std::nullptr_t x, const cycle_member_ptr<U>& y)
1912 noexcept
1913 -> bool {
1914  return bool(y);
1915 }
1916 
1919 template<typename T, typename U>
1920 inline auto operator<(const cycle_member_ptr<T>& x, const cycle_member_ptr<U>& y)
1921 noexcept
1922 -> bool {
1923  return x.get() < y.get();
1924 }
1925 
1928 template<typename T>
1929 inline auto operator<(const cycle_member_ptr<T>& x, [[maybe_unused]] std::nullptr_t y)
1930 noexcept
1931 -> bool {
1932  return std::less<typename cycle_member_ptr<T>::element_type*>()(x.get(), nullptr);
1933 }
1934 
1937 template<typename U>
1938 inline auto operator<([[maybe_unused]] std::nullptr_t x, const cycle_member_ptr<U>& y)
1939 noexcept
1940 -> bool {
1941  return std::less<typename cycle_member_ptr<U>::element_type*>()(nullptr, y.get());
1942 }
1943 
1946 template<typename T, typename U>
1947 inline auto operator>(const cycle_member_ptr<T>& x, const cycle_member_ptr<U>& y)
1948 noexcept
1949 -> bool {
1950  return y < x;
1951 }
1952 
1955 template<typename T>
1956 inline auto operator>(const cycle_member_ptr<T>& x, [[maybe_unused]] std::nullptr_t y)
1957 noexcept
1958 -> bool {
1959  return nullptr < x;
1960 }
1961 
1964 template<typename U>
1965 inline auto operator>([[maybe_unused]] std::nullptr_t x, const cycle_member_ptr<U>& y)
1966 noexcept
1967 -> bool {
1968  return y < nullptr;
1969 }
1970 
1973 template<typename T, typename U>
1974 inline auto operator<=(const cycle_member_ptr<T>& x, const cycle_member_ptr<U>& y)
1975 noexcept
1976 -> bool {
1977  return !(y < x);
1978 }
1979 
1982 template<typename T>
1983 inline auto operator<=(const cycle_member_ptr<T>& x, [[maybe_unused]] std::nullptr_t y)
1984 noexcept
1985 -> bool {
1986  return !(nullptr < x);
1987 }
1988 
1991 template<typename U>
1992 inline auto operator<=([[maybe_unused]] std::nullptr_t x, const cycle_member_ptr<U>& y)
1993 noexcept
1994 -> bool {
1995  return !(y < nullptr);
1996 }
1997 
2000 template<typename T, typename U>
2001 inline auto operator>=(const cycle_member_ptr<T>& x, const cycle_member_ptr<U>& y)
2002 noexcept
2003 -> bool {
2004  return !(x < y);
2005 }
2006 
2009 template<typename T>
2010 inline auto operator>=(const cycle_member_ptr<T>& x, [[maybe_unused]] std::nullptr_t y)
2011 noexcept
2012 -> bool {
2013  return !(x < nullptr);
2014 }
2015 
2018 template<typename U>
2019 inline auto operator>=([[maybe_unused]] std::nullptr_t x, const cycle_member_ptr<U>& y)
2020 noexcept
2021 -> bool {
2022  return !(nullptr < y);
2023 }
2024 
2027 template<typename T>
2029 noexcept
2030 -> void {
2031  x.swap(y);
2032 }
2033 
2037 template<typename T>
2039 noexcept
2040 -> void {
2041  x.swap(y);
2042 }
2043 
2044 
2047 template<typename T, typename U>
2048 inline auto operator==(const cycle_gptr<T>& x, const cycle_gptr<U>& y)
2049 noexcept
2050 -> bool {
2051  return x.get() == y.get();
2052 }
2053 
2056 template<typename T>
2057 inline auto operator==(const cycle_gptr<T>& x, [[maybe_unused]] std::nullptr_t y)
2058 noexcept
2059 -> bool {
2060  return !x;
2061 }
2062 
2065 template<typename U>
2066 inline auto operator==([[maybe_unused]] std::nullptr_t x, const cycle_gptr<U>& y)
2067 noexcept
2068 -> bool {
2069  return !y;
2070 }
2071 
2074 template<typename T, typename U>
2075 inline auto operator!=(const cycle_gptr<T>& x, const cycle_gptr<U>& y)
2076 noexcept
2077 -> bool {
2078  return !(x == y);
2079 }
2080 
2083 template<typename T>
2084 inline auto operator!=(const cycle_gptr<T>& x, [[maybe_unused]] std::nullptr_t y)
2085 noexcept
2086 -> bool {
2087  return bool(x);
2088 }
2089 
2092 template<typename U>
2093 inline auto operator!=([[maybe_unused]] std::nullptr_t x, const cycle_gptr<U>& y)
2094 noexcept
2095 -> bool {
2096  return bool(y);
2097 }
2098 
2101 template<typename T, typename U>
2102 inline auto operator<(const cycle_gptr<T>& x, const cycle_gptr<U>& y)
2103 noexcept
2104 -> bool {
2105  return x.get() < y.get();
2106 }
2107 
2110 template<typename T>
2111 inline auto operator<(const cycle_gptr<T>& x, [[maybe_unused]] std::nullptr_t y)
2112 noexcept
2113 -> bool {
2114  return std::less<typename cycle_gptr<T>::element_type*>()(x.get(), nullptr);
2115 }
2116 
2119 template<typename U>
2120 inline auto operator<([[maybe_unused]] std::nullptr_t x, const cycle_gptr<U>& y)
2121 noexcept
2122 -> bool {
2123  return std::less<typename cycle_gptr<U>::element_type*>()(nullptr, y.get());
2124 }
2125 
2128 template<typename T, typename U>
2129 inline auto operator>(const cycle_gptr<T>& x, const cycle_gptr<U>& y)
2130 noexcept
2131 -> bool {
2132  return y < x;
2133 }
2134 
2137 template<typename T>
2138 inline auto operator>(const cycle_gptr<T>& x, [[maybe_unused]] std::nullptr_t y)
2139 noexcept
2140 -> bool {
2141  return nullptr < x;
2142 }
2143 
2146 template<typename U>
2147 inline auto operator>([[maybe_unused]] std::nullptr_t x, const cycle_gptr<U>& y)
2148 noexcept
2149 -> bool {
2150  return y < nullptr;
2151 }
2152 
2155 template<typename T, typename U>
2156 inline auto operator<=(const cycle_gptr<T>& x, const cycle_gptr<U>& y)
2157 noexcept
2158 -> bool {
2159  return !(y < x);
2160 }
2161 
2164 template<typename T>
2165 inline auto operator<=(const cycle_gptr<T>& x, [[maybe_unused]] std::nullptr_t y)
2166 noexcept
2167 -> bool {
2168  return !(nullptr < x);
2169 }
2170 
2173 template<typename U>
2174 inline auto operator<=([[maybe_unused]] std::nullptr_t x, const cycle_gptr<U>& y)
2175 noexcept
2176 -> bool {
2177  return !(y < nullptr);
2178 }
2179 
2182 template<typename T, typename U>
2183 inline auto operator>=(const cycle_gptr<T>& x, const cycle_gptr<U>& y)
2184 noexcept
2185 -> bool {
2186  return !(x < y);
2187 }
2188 
2191 template<typename T>
2192 inline auto operator>=(const cycle_gptr<T>& x, [[maybe_unused]] std::nullptr_t y)
2193 noexcept
2194 -> bool {
2195  return !(x < nullptr);
2196 }
2197 
2200 template<typename U>
2201 inline auto operator>=([[maybe_unused]] std::nullptr_t x, const cycle_gptr<U>& y)
2202 noexcept
2203 -> bool {
2204  return !(nullptr < y);
2205 }
2206 
2209 template<typename T>
2210 inline auto swap(cycle_gptr<T>& x, cycle_gptr<T>& y)
2211 noexcept
2212 -> void {
2213  x.swap(y);
2214 }
2215 
2219 template<typename T>
2221 noexcept
2222 -> void {
2223  x.swap(y);
2224 }
2225 
2226 
2229 template<typename T>
2231 noexcept
2232 -> void {
2233  x.swap(y);
2234 }
2235 
2236 
2240 template<typename T, typename U>
2241 inline auto operator==(const cycle_gptr<T>& x, const cycle_member_ptr<U>& y)
2242 noexcept
2243 -> bool {
2244  return x.get() == y.get();
2245 }
2246 
2250 template<typename T, typename U>
2251 inline auto operator==(const cycle_member_ptr<T>& x, const cycle_gptr<U>& y)
2252 noexcept
2253 -> bool {
2254  return x.get() == y.get();
2255 }
2256 
2260 template<typename T, typename U>
2261 inline auto operator!=(const cycle_gptr<T>& x, const cycle_member_ptr<U>& y)
2262 noexcept
2263 -> bool {
2264  return !(x == y);
2265 }
2266 
2270 template<typename T, typename U>
2271 inline auto operator!=(const cycle_member_ptr<T>& x, const cycle_gptr<U>& y)
2272 noexcept
2273 -> bool {
2274  return !(x == y);
2275 }
2276 
2280 template<typename T, typename U>
2281 inline auto operator<(const cycle_gptr<T>& x, const cycle_member_ptr<U>& y)
2282 noexcept
2283 -> bool {
2284  return x.get() < y.get();
2285 }
2286 
2290 template<typename T, typename U>
2291 inline auto operator<(const cycle_member_ptr<T>& x, const cycle_gptr<U>& y)
2292 noexcept
2293 -> bool {
2294  return x.get() < y.get();
2295 }
2296 
2300 template<typename T, typename U>
2301 inline auto operator>(const cycle_gptr<T>& x, const cycle_member_ptr<U>& y)
2302 noexcept
2303 -> bool {
2304  return y < x;
2305 }
2306 
2310 template<typename T, typename U>
2311 inline auto operator>(const cycle_member_ptr<T>& x, const cycle_gptr<U>& y)
2312 noexcept
2313 -> bool {
2314  return y < x;
2315 }
2316 
2320 template<typename T, typename U>
2321 inline auto operator<=(const cycle_gptr<T>& x, const cycle_member_ptr<U>& y)
2322 noexcept
2323 -> bool {
2324  return !(y < x);
2325 }
2326 
2330 template<typename T, typename U>
2331 inline auto operator<=(const cycle_member_ptr<T>& x, const cycle_gptr<U>& y)
2332 noexcept
2333 -> bool {
2334  return !(y < x);
2335 }
2336 
2340 template<typename T, typename U>
2341 inline auto operator>=(const cycle_gptr<T>& x, const cycle_member_ptr<U>& y)
2342 noexcept
2343 -> bool {
2344  return !(x < y);
2345 }
2346 
2350 template<typename T, typename U>
2351 inline auto operator>=(const cycle_member_ptr<T>& x, const cycle_gptr<U>& y)
2352 noexcept
2353 -> bool {
2354  return !(x < y);
2355 }
2356 
2357 
2369 template<typename T, typename Alloc, typename... Args>
2370 auto allocate_cycle(Alloc alloc, Args&&... args)
2371 -> cycle_gptr<T> {
2372  using alloc_t = typename std::allocator_traits<Alloc>::template rebind_alloc<T>;
2373  using control_t = detail::control<T, alloc_t>;
2374  using alloc_traits = typename std::allocator_traits<Alloc>::template rebind_traits<control_t>;
2375  using ctrl_alloc_t = typename std::allocator_traits<Alloc>::template rebind_alloc<control_t>;
2376 
2377  ctrl_alloc_t ctrl_alloc = alloc;
2378 
2379  control_t* raw_ctrl_ptr = alloc_traits::allocate(ctrl_alloc, 1);
2380  try {
2381  alloc_traits::construct(ctrl_alloc, raw_ctrl_ptr, ctrl_alloc);
2382  } catch (...) {
2383  alloc_traits::deallocate(ctrl_alloc, raw_ctrl_ptr, 1);
2384  throw;
2385  }
2386  auto ctrl_ptr = detail::intrusive_ptr<detail::base_control>(raw_ctrl_ptr, false);
2387  T* elem_ptr = raw_ctrl_ptr->instantiate(std::forward<Args>(args)...);
2388 
2389  cycle_gptr<T> result;
2390  result.emplace_(elem_ptr, std::move(ctrl_ptr));
2391  return result;
2392 }
2393 
2406 template<typename T, typename... Args>
2407 auto make_cycle(Args&&... args)
2408 -> cycle_gptr<T> {
2409  return allocate_cycle<T>(std::allocator<T>(), std::forward<Args>(args)...);
2410 }
2411 
2412 
2415 template<typename Char, typename Traits, typename T>
2416 auto operator<<(std::basic_ostream<Char, Traits>& out, const cycle_member_ptr<T>& ptr)
2417 -> std::basic_ostream<Char, Traits>& {
2418  return out << ptr.get();
2419 }
2420 
2423 template<typename Char, typename Traits, typename T>
2424 auto operator<<(std::basic_ostream<Char, Traits>& out, const cycle_gptr<T>& ptr)
2425 -> std::basic_ostream<Char, Traits>& {
2426  return out << ptr.get();
2427 }
2428 
2429 
2430 } /* namespace cycle_ptr */
2431 
2432 namespace std {
2433 
2434 
2445 template<typename T, typename U = cycle_ptr::cycle_gptr<T>>
2447  cycle_ptr::cycle_gptr<T> result = std::move(x);
2448  x = std::forward<U>(y);
2449  return result;
2450 }
2451 
2459 template<typename T>
2460 struct hash<cycle_ptr::cycle_member_ptr<T>> {
2463  [[deprecated]]
2467  [[deprecated]]
2468  typedef std::size_t result_type;
2469 
2477  noexcept
2478  -> std::size_t {
2479  return std::hash<typename cycle_ptr::cycle_member_ptr<T>::element_type*>()(p.get());
2480  }
2481 
2489  noexcept
2490  -> std::size_t {
2491  return std::hash<typename cycle_ptr::cycle_gptr<T>::element_type*>()(p.get());
2492  }
2493 };
2494 
2502 template<typename T>
2503 struct hash<cycle_ptr::cycle_gptr<T>>
2504 : hash<cycle_ptr::cycle_member_ptr<T>>
2505 {
2508  [[deprecated]]
2510 };
2511 
2512 
2515 template<typename T, typename U>
2518  return cycle_ptr::cycle_gptr<T>(
2519  r,
2520  static_cast<typename cycle_ptr::cycle_gptr<T>::element_type*>(r.get()));
2521 }
2522 
2525 template<typename T, typename U>
2528  return cycle_ptr::cycle_gptr<T>(
2529  r,
2530  dynamic_cast<typename cycle_ptr::cycle_gptr<T>::element_type*>(r.get()));
2531 }
2532 
2535 template<typename T, typename U>
2538  return cycle_ptr::cycle_gptr<T>(
2539  r,
2540  const_cast<typename cycle_ptr::cycle_gptr<T>::element_type*>(r.get()));
2541 }
2542 
2545 template<typename T, typename U>
2548  return cycle_ptr::cycle_gptr<T>(
2549  r,
2550  reinterpret_cast<typename cycle_ptr::cycle_gptr<T>::element_type*>(r.get()));
2551 }
2552 
2553 
2556 template<typename T, typename U>
2559  return cycle_ptr::cycle_gptr<T>(
2560  r,
2561  static_cast<typename cycle_ptr::cycle_gptr<T>::element_type*>(r.get()));
2562 }
2563 
2566 template<typename T, typename U>
2569  return cycle_ptr::cycle_gptr<T>(
2570  r,
2571  dynamic_cast<typename cycle_ptr::cycle_gptr<T>::element_type*>(r.get()));
2572 }
2573 
2576 template<typename T, typename U>
2579  return cycle_ptr::cycle_gptr<T>(
2580  r,
2581  const_cast<typename cycle_ptr::cycle_gptr<T>::element_type*>(r.get()));
2582 }
2583 
2586 template<typename T, typename U>
2589  return cycle_ptr::cycle_gptr<T>(
2590  r,
2591  reinterpret_cast<typename cycle_ptr::cycle_gptr<T>::element_type*>(r.get()));
2592 }
2593 
2594 
2595 } /* namespace std */
2596 
2597 #endif /* CYCLE_PTR_CYCLE_PTR_H */
auto operator<(const cycle_member_ptr< T > &x, [[maybe_unused]] std::nullptr_t y) noexcept -> bool
Less comparison.
Definition: cycle_ptr.h:1929
auto operator=(cycle_weak_ptr< U > &&other) noexcept -> cycle_weak_ptr &
Move assignment.
Definition: cycle_ptr.h:1761
cycle_member_ptr(cycle_base &owner, [[maybe_unused]] std::nullptr_t nil) noexcept
Constructor with explicitly specified ownership.
Definition: cycle_ptr.h:538
auto operator<(const cycle_gptr< T > &x, const cycle_member_ptr< U > &y) noexcept -> bool
Less comparison.
Definition: cycle_ptr.h:2281
auto operator>=([[maybe_unused]] std::nullptr_t x, const cycle_member_ptr< U > &y) noexcept -> bool
Greater or equal comparison.
Definition: cycle_ptr.h:2019
auto operator()(const cycle_ptr::cycle_gptr< T > &p) const noexcept -> std::size_t
Compute the hashcode of a cycle pointer.
Definition: cycle_ptr.h:2488
cycle_gptr(cycle_gptr< U > &&other) noexcept
Move constructor.
Definition: cycle_ptr.h:1304
constexpr cycle_gptr() noexcept
Default constructor.
Definition: cycle_ptr.h:1249
cycle_member_ptr(cycle_base &owner, const cycle_member_ptr< U > &ptr)
Constructor with explicitly specified ownership.
Definition: cycle_ptr.h:554
cycle_base([[maybe_unused]] unowned_cycle_t unowned_tag)
Specialized constructor that signifies *this will not be pointed at by a cycle_ptr.
Definition: cycle_ptr.h:71
auto operator<=(const cycle_gptr< T > &x, const cycle_gptr< U > &y) noexcept -> bool
Less or equal comparison.
Definition: cycle_ptr.h:2156
auto const_pointer_cast(const cycle_ptr::cycle_gptr< U > &r) -> cycle_ptr::cycle_gptr< T >
Perform const cast on pointer.
Definition: cycle_ptr.h:2536
auto dynamic_pointer_cast(const cycle_ptr::cycle_gptr< U > &r) -> cycle_ptr::cycle_gptr< T >
Perform dynamic cast on pointer.
Definition: cycle_ptr.h:2526
cycle_member_ptr([[maybe_unused]] unowned_cycle_t unowned_tag, const cycle_member_ptr< U > &ptr)
Create an unowned member pointer, pointing at ptr.
Definition: cycle_ptr.h:277
auto operator *() const -> std::enable_if_t< Enable, T > &
Dereference operation.
Definition: cycle_ptr.h:1575
auto operator=(const cycle_weak_ptr &other) noexcept -> cycle_weak_ptr &
Copy assignment.
Definition: cycle_ptr.h:1730
auto static_pointer_cast(const cycle_ptr::cycle_member_ptr< U > &r) -> cycle_ptr::cycle_gptr< T >
Perform static cast on pointer.
Definition: cycle_ptr.h:2557
auto operator>(const cycle_member_ptr< T > &x, const cycle_member_ptr< U > &y) noexcept -> bool
Greater comparison.
Definition: cycle_ptr.h:1947
auto operator!=(const cycle_gptr< T > &x, [[maybe_unused]] std::nullptr_t y) noexcept -> bool
Inequality comparison.
Definition: cycle_ptr.h:2084
std::remove_extent_t< T > element_type
Element type of this pointer.
Definition: cycle_ptr.h:1243
Adaptor for collections with member types.
Definition: allocator.h:19
auto lock() const noexcept -> cycle_gptr< T >
Retrieve cycle_gptr from this.
Definition: cycle_ptr.h:1822
cycle_member_ptr(const cycle_member_ptr< U > &ptr)
Constructor with automatic ownership detection.
Definition: cycle_ptr.h:809
cycle_member_ptr(cycle_base &owner, const cycle_gptr< U > &ptr, element_type *target)
Aliasing constructor with explicitly specified ownership.
Definition: cycle_ptr.h:676
auto allocate_cycle(Alloc alloc, Args &&... args) -> cycle_gptr< T >
Allocate a new instance of T, using the specificied allocator.
Definition: cycle_ptr.h:2370
cycle_base(const cycle_base &) noexcept
Copy constructor.
Definition: cycle_ptr.h:85
auto operator=(const cycle_base &) noexcept -> cycle_base &
Copy assignment.
Definition: cycle_ptr.h:95
auto operator<<(std::basic_ostream< Char, Traits > &out, const cycle_gptr< T > &ptr) -> std::basic_ostream< Char, Traits > &
Write pointer to output stream.
Definition: cycle_ptr.h:2424
auto throw_if_owner_expired() const -> void
Throw exception if owner is expired.
Definition: vertex.h:57
cycle_member_ptr([[maybe_unused]] unowned_cycle_t unowned_tag, const cycle_member_ptr< U > &ptr, element_type *target)
Aliasing constructor for unowned member pointer.
Definition: cycle_ptr.h:440
cycle_member_ptr(cycle_member_ptr< U > &&ptr)
Constructor with automatic ownership detection.
Definition: cycle_ptr.h:838
auto operator<=(const cycle_gptr< T > &x, [[maybe_unused]] std::nullptr_t y) noexcept -> bool
Less or equal comparison.
Definition: cycle_ptr.h:2165
auto operator>=([[maybe_unused]] std::nullptr_t x, const cycle_gptr< U > &y) noexcept -> bool
Greater or equal comparison.
Definition: cycle_ptr.h:2201
auto swap(cycle_gptr &other) noexcept -> void
Swap with other.
Definition: cycle_ptr.h:1539
auto dynamic_pointer_cast(const cycle_ptr::cycle_member_ptr< U > &r) -> cycle_ptr::cycle_gptr< T >
Perform dynamic cast on pointer.
Definition: cycle_ptr.h:2567
auto owner_before(const cycle_weak_ptr< U > &other) const noexcept -> bool
Ownership ordering.
Definition: cycle_ptr.h:1833
auto operator>(const cycle_gptr< T > &x, [[maybe_unused]] std::nullptr_t y) noexcept -> bool
Greater comparison.
Definition: cycle_ptr.h:2138
cycle_base()
Default constructor acquires its control block from context.
Definition: cycle_ptr.h:62
auto operator=(cycle_weak_ptr &&other) noexcept -> cycle_weak_ptr &
Move assignment.
Definition: cycle_ptr.h:1740
auto reinterpret_pointer_cast(const cycle_ptr::cycle_gptr< U > &r) -> cycle_ptr::cycle_gptr< T >
Perform reinterpret cast on pointer.
Definition: cycle_ptr.h:2546
cycle_gptr(const cycle_gptr< U > &other, element_type *target) noexcept
Aliasing constructor.
Definition: cycle_ptr.h:1351
auto static_pointer_cast(const cycle_ptr::cycle_gptr< U > &r) -> cycle_ptr::cycle_gptr< T >
Perform static cast on pointer.
Definition: cycle_ptr.h:2516
auto owner_before(const cycle_member_ptr< U > &other) const noexcept -> bool
Ownership ordering.
Definition: cycle_ptr.h:1618
auto operator<=(const cycle_member_ptr< T > &x, const cycle_gptr< U > &y) noexcept -> bool
Less or equal comparison.
Definition: cycle_ptr.h:2331
auto swap(cycle_gptr< T > &other) -> void
Swap with other pointer.
Definition: cycle_ptr.h:1139
auto operator=(cycle_member_ptr &&other) -> cycle_member_ptr &
Move assignment operator.
Definition: cycle_ptr.h:1020
auto owner_before(const cycle_weak_ptr< U > &other) const noexcept -> bool
Ownership ordering.
Definition: cycle_ptr.h:1602
auto reinterpret_pointer_cast(const cycle_ptr::cycle_member_ptr< U > &r) -> cycle_ptr::cycle_gptr< T >
Perform reinterpret cast on pointer.
Definition: cycle_ptr.h:2587
auto swap(cycle_member_ptr< T > &x, cycle_gptr< T > &y) noexcept -> void
Swap two pointers.
Definition: cycle_ptr.h:2038
cycle_member_ptr(cycle_base &owner, const cycle_member_ptr< U > &ptr, element_type *target)
Aliasing constructor with explicitly specified ownership.
Definition: cycle_ptr.h:647
auto reset() -> void
Clear this pointer.
Definition: cycle_ptr.h:1108
auto swap(cycle_member_ptr &other) -> void
Swap with other pointer.
Definition: cycle_ptr.h:1123
auto operator>=(const cycle_member_ptr< T > &x, const cycle_member_ptr< U > &y) noexcept -> bool
Greater or equal comparison.
Definition: cycle_ptr.h:2001
auto operator>([[maybe_unused]] std::nullptr_t x, const cycle_member_ptr< U > &y) noexcept -> bool
Greater comparison.
Definition: cycle_ptr.h:1965
auto swap(cycle_member_ptr< T > &other) -> void
Swap with other.
Definition: cycle_ptr.h:1556
auto operator==(const cycle_member_ptr< T > &x, const cycle_member_ptr< U > &y) noexcept -> bool
Equality comparison.
Definition: cycle_ptr.h:1866
Intrusive pointer.
Definition: intrusive_ptr.h:21
auto shared_from_this(T *this_ptr) const -> cycle_gptr< T >
Create a cycle_gptr (equivalent of std::shared_ptr) from this.
Definition: cycle_ptr.h:119
auto operator=(const cycle_member_ptr< U > &other) -> cycle_gptr &
Copy assignment.
Definition: cycle_ptr.h:1479
cycle_gptr(cycle_gptr &&other) noexcept
Move constructor.
Definition: cycle_ptr.h:1277
cycle_gptr(const cycle_gptr< U > &other) noexcept
Copy constructor.
Definition: cycle_ptr.h:1288
auto swap(cycle_weak_ptr &other) noexcept -> void
Swap with another weak pointer.
Definition: cycle_ptr.h:1801
auto owner_before(const cycle_member_ptr< U > &other) const noexcept -> bool
Ownership ordering.
Definition: cycle_ptr.h:1209
auto operator>=(const cycle_gptr< T > &x, const cycle_member_ptr< U > &y) noexcept -> bool
Greater or equal comparison.
Definition: cycle_ptr.h:2341
auto operator<(const cycle_member_ptr< T > &x, const cycle_gptr< U > &y) noexcept -> bool
Less comparison.
Definition: cycle_ptr.h:2291
auto operator=(const cycle_member_ptr< U > &other) -> cycle_member_ptr &
Copy assignment operator.
Definition: cycle_ptr.h:1038
auto operator>(const cycle_member_ptr< T > &x, [[maybe_unused]] std::nullptr_t y) noexcept -> bool
Greater comparison.
Definition: cycle_ptr.h:1956
auto swap(cycle_member_ptr< T > &x, cycle_member_ptr< T > &y) noexcept -> void
Swap two pointers.
Definition: cycle_ptr.h:2028
cycle_gptr(const cycle_member_ptr< U > &other)
Copy constructor.
Definition: cycle_ptr.h:1317
auto operator<(const cycle_gptr< T > &x, [[maybe_unused]] std::nullptr_t y) noexcept -> bool
Less comparison.
Definition: cycle_ptr.h:2111
auto operator<<(std::basic_ostream< Char, Traits > &out, const cycle_member_ptr< T > &ptr) -> std::basic_ostream< Char, Traits > &
Write pointer to output stream.
Definition: cycle_ptr.h:2416
std::remove_extent_t< T > element_type
Element type of this pointer.
Definition: cycle_ptr.h:1677
auto operator>(const cycle_gptr< T > &x, const cycle_member_ptr< U > &y) noexcept -> bool
Greater comparison.
Definition: cycle_ptr.h:2301
auto operator!=([[maybe_unused]] std::nullptr_t x, const cycle_gptr< U > &y) noexcept -> bool
Inequality comparison.
Definition: cycle_ptr.h:2093
cycle_member_ptr(const cycle_member_ptr< U > &ptr, element_type *target)
Aliasing constructor with automatic ownership detection.
Definition: cycle_ptr.h:921
auto operator!=(const cycle_member_ptr< T > &x, [[maybe_unused]] std::nullptr_t y) noexcept -> bool
Inequality comparison.
Definition: cycle_ptr.h:1902
auto operator==([[maybe_unused]] std::nullptr_t x, const cycle_member_ptr< U > &y) noexcept -> bool
Equality comparison.
Definition: cycle_ptr.h:1884
auto operator=(const cycle_gptr< U > &other) -> cycle_member_ptr &
Copy assignment operator.
Definition: cycle_ptr.h:1074
cycle_weak_ptr(const cycle_member_ptr< U > &other) noexcept
Create weak pointer from other.
Definition: cycle_ptr.h:1724
cycle_member_ptr()
Constructor with automatic ownership detection.
Definition: cycle_ptr.h:716
cycle_ptr::cycle_member_ptr< T > argument_type
Argument type.
Definition: cycle_ptr.h:2464
cycle_member_ptr(cycle_base &owner, cycle_member_ptr< U > &&ptr)
Constructor with explicitly specified ownership.
Definition: cycle_ptr.h:577
auto operator=(const cycle_gptr< U > &other) noexcept -> cycle_weak_ptr &
Assign other. post this->lock() == other.
Definition: cycle_ptr.h:1772
cycle_member_ptr(const cycle_member_ptr &ptr)
Constructor with automatic ownership detection.
Definition: cycle_ptr.h:756
cycle_member_ptr(unowned_cycle_t unowned_tag, cycle_member_ptr< U > &&ptr)
Create an unowned member pointer, pointing at ptr.
Definition: cycle_ptr.h:324
cycle_member_ptr(cycle_base &owner, const cycle_gptr< U > &ptr)
Constructor with explicitly specified ownership.
Definition: cycle_ptr.h:595
auto operator>=(const cycle_member_ptr< T > &x, [[maybe_unused]] std::nullptr_t y) noexcept -> bool
Greater or equal comparison.
Definition: cycle_ptr.h:2010
auto reset() noexcept -> void
Clear this pointer.
Definition: cycle_ptr.h:1521
auto operator=(cycle_member_ptr< U > &&other) -> cycle_member_ptr &
Move assignment operator.
Definition: cycle_ptr.h:1059
auto owner_before(const cycle_weak_ptr< U > &other) const noexcept -> bool
Ownership ordering.
Definition: cycle_ptr.h:1193
cycle_member_ptr(unowned_cycle_t unowned_tag, const cycle_weak_ptr< U > &ptr)
Create an unowned member pointer, pointing at ptr.
Definition: cycle_ptr.h:509
auto operator<(const cycle_gptr< T > &x, const cycle_gptr< U > &y) noexcept -> bool
Less comparison.
Definition: cycle_ptr.h:2102
auto reset() noexcept -> void
Reset this pointer.
Definition: cycle_ptr.h:1793
auto operator<([[maybe_unused]] std::nullptr_t x, const cycle_member_ptr< U > &y) noexcept -> bool
Less comparison.
Definition: cycle_ptr.h:1938
~cycle_base() noexcept=default
Default destructor.
auto operator->() const -> std::enable_if_t< Enable, T > *
Indirection operation.
Definition: cycle_ptr.h:1586
auto operator==(const cycle_member_ptr< T > &x, const cycle_gptr< U > &y) noexcept -> bool
Equality comparison.
Definition: cycle_ptr.h:2251
auto exchange(cycle_ptr::cycle_member_ptr< T > &x, U &&y)
Specialize std::exchange.
Definition: cycle_ptr.h:2446
auto operator!=([[maybe_unused]] std::nullptr_t x, const cycle_member_ptr< U > &y) noexcept -> bool
Inequality comparison.
Definition: cycle_ptr.h:1911
auto owner_before(const cycle_member_ptr< U > &other) const noexcept -> bool
Ownership ordering.
Definition: cycle_ptr.h:1849
auto operator=([[maybe_unused]] std::nullptr_t nil) -> cycle_member_ptr &
Assignment operator.
Definition: cycle_ptr.h:986
auto get() const noexcept -> T *
Retrieve address of this pointer.
Definition: cycle_ptr.h:1564
cycle_member_ptr(const cycle_weak_ptr< U > &ptr)
Constructor with automatic ownership detection.
Definition: cycle_ptr.h:975
cycle_member_ptr([[maybe_unused]] unowned_cycle_t unowned_tag) noexcept
Create an unowned member pointer, representing a nullptr.
Definition: cycle_ptr.h:198
cycle_ptr::cycle_gptr< T > argument_type
Argument type.
Definition: cycle_ptr.h:2509
auto swap(cycle_weak_ptr< T > &x, cycle_weak_ptr< T > &y) noexcept -> void
Swap two pointers.
Definition: cycle_ptr.h:2230
auto owner_before(const cycle_gptr< U > &other) const noexcept -> bool
Ownership ordering.
Definition: cycle_ptr.h:1201
auto operator<=([[maybe_unused]] std::nullptr_t x, const cycle_gptr< U > &y) noexcept -> bool
Less or equal comparison.
Definition: cycle_ptr.h:2174
auto get_control() const noexcept -> intrusive_ptr< base_control >
Read the target control block.
auto operator<(const cycle_member_ptr< T > &x, const cycle_member_ptr< U > &y) noexcept -> bool
Less comparison.
Definition: cycle_ptr.h:1920
cycle_member_ptr([[maybe_unused]] unowned_cycle_t unowned_tag, cycle_gptr< U > &&ptr)
Create an unowned member pointer, pointing at ptr.
Definition: cycle_ptr.h:412
Control block implementation for given type and allocator combination.
Definition: control.h:24
cycle_weak_ptr(const cycle_weak_ptr< U > &other) noexcept
Copy constructor.
Definition: cycle_ptr.h:1700
auto operator->() const -> std::enable_if_t< Enable, T > *
Indirection operation.
Definition: cycle_ptr.h:1176
cycle_member_ptr([[maybe_unused]] unowned_cycle_t unowned_tag, const cycle_gptr< U > &ptr, element_type *target)
Aliasing constructor for unowned member pointer.
Definition: cycle_ptr.h:465
cycle_gptr(const cycle_gptr &other) noexcept
Copy constructor.
Definition: cycle_ptr.h:1262
auto operator<([[maybe_unused]] std::nullptr_t x, const cycle_gptr< U > &y) noexcept -> bool
Less comparison.
Definition: cycle_ptr.h:2120
Tag indicating an edge without owner.
Definition: cycle_ptr.h:24
cycle_member_ptr([[maybe_unused]] std::nullptr_t nil)
Constructor with automatic ownership detection.
Definition: cycle_ptr.h:736
cycle_member_ptr(const cycle_gptr< U > &ptr)
Constructor with automatic ownership detection.
Definition: cycle_ptr.h:863
auto make_cycle(Args &&... args) -> cycle_gptr< T >
Allocate a new instance of T, using the default allocator.
Definition: cycle_ptr.h:2407
cycle_gptr(const cycle_member_ptr< U > &other, element_type *target)
Aliasing constructor.
Definition: cycle_ptr.h:1369
auto swap(cycle_gptr< T > &x, cycle_gptr< T > &y) noexcept -> void
Swap two pointers.
Definition: cycle_ptr.h:2210
auto owner_before(const cycle_gptr< U > &other) const noexcept -> bool
Ownership ordering.
Definition: cycle_ptr.h:1610
cycle_weak_ptr(cycle_weak_ptr &&other) noexcept
Move constructor.
Definition: cycle_ptr.h:1693
cycle_member_ptr(cycle_gptr< U > &&ptr)
Constructor with automatic ownership detection.
Definition: cycle_ptr.h:891
Weak cycle pointer.
Definition: cycle_ptr.h:34
auto operator!=(const cycle_member_ptr< T > &x, const cycle_gptr< U > &y) noexcept -> bool
Inequality comparison.
Definition: cycle_ptr.h:2271
auto expired() const noexcept -> bool
Test if this weak pointer is expired.
Definition: cycle_ptr.h:1810
auto operator=(cycle_gptr< U > &&other) -> cycle_member_ptr &
Move assignment operator.
Definition: cycle_ptr.h:1092
auto swap(cycle_gptr< T > &x, cycle_member_ptr< T > &y) noexcept -> void
Swap two pointers.
Definition: cycle_ptr.h:2220
auto operator==(const cycle_gptr< T > &x, const cycle_gptr< U > &y) noexcept -> bool
Equality comparison.
Definition: cycle_ptr.h:2048
cycle_gptr(const cycle_weak_ptr< U > &other)
Construct from cycle_weak_ptr.
Definition: cycle_ptr.h:1385
auto operator=(cycle_gptr &&other) noexcept -> cycle_gptr &
Move assignment.
Definition: cycle_ptr.h:1419
auto operator=(cycle_gptr< U > &&other) noexcept -> cycle_gptr &
Move assignment.
Definition: cycle_ptr.h:1459
auto operator<=(const cycle_member_ptr< T > &x, [[maybe_unused]] std::nullptr_t y) noexcept -> bool
Less or equal comparison.
Definition: cycle_ptr.h:1983
auto operator!=(const cycle_member_ptr< T > &x, const cycle_member_ptr< U > &y) noexcept -> bool
Inequality comparison.
Definition: cycle_ptr.h:1893
An optional base for classes which need to supply ownership to cycle_member_ptr.
Definition: cycle_ptr.h:49
auto operator=(const cycle_gptr< U > &other) noexcept -> cycle_gptr &
Copy assignment.
Definition: cycle_ptr.h:1437
cycle_weak_ptr(const cycle_weak_ptr &other) noexcept
Copy constructor.
Definition: cycle_ptr.h:1683
auto operator=(cycle_member_ptr< U > &&other) -> cycle_gptr &
Move assignment.
Definition: cycle_ptr.h:1504
auto operator>=(const cycle_gptr< T > &x, [[maybe_unused]] std::nullptr_t y) noexcept -> bool
Greater or equal comparison.
Definition: cycle_ptr.h:2192
static auto unowned_control() -> intrusive_ptr< base_control >
Create a control block that represents no ownership.
auto operator=(const cycle_member_ptr &other) -> cycle_member_ptr &
Copy assignment operator.
Definition: cycle_ptr.h:1000
auto operator==(const cycle_gptr< T > &x, [[maybe_unused]] std::nullptr_t y) noexcept -> bool
Equality comparison.
Definition: cycle_ptr.h:2057
auto operator!=(const cycle_gptr< T > &x, const cycle_member_ptr< U > &y) noexcept -> bool
Inequality comparison.
Definition: cycle_ptr.h:2261
Global (or automatic) scope smart pointer.
Definition: cycle_ptr.h:33
auto operator=(const cycle_gptr &other) noexcept -> cycle_gptr &
Copy assignment.
Definition: cycle_ptr.h:1398
cycle_weak_ptr(const cycle_gptr< U > &other) noexcept
Create weak pointer from other.
Definition: cycle_ptr.h:1716
auto operator<=(const cycle_gptr< T > &x, const cycle_member_ptr< U > &y) noexcept -> bool
Less or equal comparison.
Definition: cycle_ptr.h:2321
auto get() const -> T *
Returns the raw pointer of this.
Definition: cycle_ptr.h:1150
cycle_member_ptr(cycle_base &owner, const cycle_weak_ptr< U > &ptr)
Constructor with explicitly specified ownership.
Definition: cycle_ptr.h:694
cycle_member_ptr(unowned_cycle_t unowned_tag, [[maybe_unused]] std::nullptr_t nil) noexcept
Create an unowned member pointer, representing a nullptr.
Definition: cycle_ptr.h:237
auto operator>(const cycle_member_ptr< T > &x, const cycle_gptr< U > &y) noexcept -> bool
Greater comparison.
Definition: cycle_ptr.h:2311
std::remove_extent_t< T > element_type
Element type of this pointer.
Definition: cycle_ptr.h:160
auto operator==([[maybe_unused]] std::nullptr_t x, const cycle_gptr< U > &y) noexcept -> bool
Equality comparison.
Definition: cycle_ptr.h:2066
auto operator<=([[maybe_unused]] std::nullptr_t x, const cycle_member_ptr< U > &y) noexcept -> bool
Less or equal comparison.
Definition: cycle_ptr.h:1992
cycle_gptr(cycle_member_ptr< U > &&other)
Move constructor.
Definition: cycle_ptr.h:1336
auto operator()(const cycle_ptr::cycle_member_ptr< T > &p) const noexcept -> std::size_t
Compute the hashcode of a cycle pointer.
Definition: cycle_ptr.h:2476
constexpr cycle_gptr([[maybe_unused]] std::nullptr_t nil) noexcept
Nullptr constructor.
Definition: cycle_ptr.h:1253
cycle_member_ptr([[maybe_unused]] unowned_cycle_t unowned_tag, const cycle_gptr< U > &ptr)
Create an unowned member pointer, pointing at ptr.
Definition: cycle_ptr.h:366
auto operator>=(const cycle_gptr< T > &x, const cycle_gptr< U > &y) noexcept -> bool
Greater or equal comparison.
Definition: cycle_ptr.h:2183
auto operator<=(const cycle_member_ptr< T > &x, const cycle_member_ptr< U > &y) noexcept -> bool
Less or equal comparison.
Definition: cycle_ptr.h:1974
auto operator>(const cycle_gptr< T > &x, const cycle_gptr< U > &y) noexcept -> bool
Greater comparison.
Definition: cycle_ptr.h:2129
auto operator>([[maybe_unused]] std::nullptr_t x, const cycle_gptr< U > &y) noexcept -> bool
Greater comparison.
Definition: cycle_ptr.h:2147
auto operator!=(const cycle_gptr< T > &x, const cycle_gptr< U > &y) noexcept -> bool
Inequality comparison.
Definition: cycle_ptr.h:2075
std::size_t result_type
Argument type.
Definition: cycle_ptr.h:2468
auto operator==(const cycle_gptr< T > &x, const cycle_member_ptr< U > &y) noexcept -> bool
Equality comparison.
Definition: cycle_ptr.h:2241
cycle_weak_ptr(cycle_weak_ptr< U > &&other) noexcept
Move constructor.
Definition: cycle_ptr.h:1708
cycle_member_ptr(cycle_base &owner) noexcept
Constructor with explicitly specified ownership.
Definition: cycle_ptr.h:523
constexpr cycle_weak_ptr() noexcept
Default constructor.
Definition: cycle_ptr.h:1680
auto operator=(const cycle_member_ptr< U > &other) noexcept -> cycle_weak_ptr &
Assign other. post this->lock() == other.
Definition: cycle_ptr.h:1783
auto const_pointer_cast(const cycle_ptr::cycle_member_ptr< U > &r) -> cycle_ptr::cycle_gptr< T >
Perform const cast on pointer.
Definition: cycle_ptr.h:2577
cycle_member_ptr(cycle_member_ptr &&ptr)
Constructor with automatic ownership detection.
Definition: cycle_ptr.h:784
cycle_member_ptr(const cycle_gptr< U > &ptr, element_type *target)
Aliasing constructor with automatic ownership detection.
Definition: cycle_ptr.h:950
auto owner_before(const cycle_gptr< U > &other) const noexcept -> bool
Ownership ordering.
Definition: cycle_ptr.h:1841
auto operator *() const -> std::enable_if_t< Enable, T > &
Dereference operation.
Definition: cycle_ptr.h:1163
cycle_member_ptr(cycle_base &owner, cycle_gptr< U > &&ptr)
Constructor with explicitly specified ownership.
Definition: cycle_ptr.h:617
Pointer between objects participating in the cycle_ptr graph.
Definition: cycle_ptr.h:32
auto operator==(const cycle_member_ptr< T > &x, [[maybe_unused]] std::nullptr_t y) noexcept -> bool
Equality comparison.
Definition: cycle_ptr.h:1875
auto operator=(const cycle_weak_ptr< U > &other) noexcept -> cycle_weak_ptr &
Copy assignment.
Definition: cycle_ptr.h:1750
auto operator>=(const cycle_member_ptr< T > &x, const cycle_gptr< U > &y) noexcept -> bool
Greater or equal comparison.
Definition: cycle_ptr.h:2351