Bifrost SDK
Bifrost SDK documentation
Ptr.h
Go to the documentation of this file.
1//-
2// =============================================================================
3// Copyright 2025 Autodesk, Inc. All rights reserved.
4//
5// Use of this software is subject to the terms of the Autodesk license
6// agreement provided at the time of installation or download, or which
7// otherwise accompanies this software in either electronic or hard copy form.
8// =============================================================================
9//+
10
19
20#ifndef AMINO_PTR_H
21#define AMINO_PTR_H
22
23#include "PtrFwd.h"
24
25//==============================================================================
26// EXTERNAL DECLARATIONS
27//==============================================================================
28
29#include "internal/PtrRep.h"
30
31#include <functional>
32#include <type_traits>
33
34namespace Amino {
35
36//==============================================================================
37// Forward declarations
38//==============================================================================
39
40namespace Internal {
41struct PtrCast;
42} // namespace Internal
43
44//==============================================================================
45// Traits
46//==============================================================================
47
59 template <typename T>
61 : public std::integral_constant<
62 bool,
63 // The pointee must not be a pointer itself.
64 (!std::is_pointer<T>::value &&
65
66 // The pointee must not be a reference.
67 !std::is_reference<T>::value &&
68
69 // The type must not include "const" qualifiers.
70 // By definition, Ptr<T> points to a const T.
71 // By definition, MutablePtr<T> points to a non-const T.
72 !std::is_const<T>::value &&
73
74 // The type must not include "volatile" qualifiers.
75 !std::is_volatile<T>::value &&
76
77 // The type must not be an array (e.g. int[]).
78 !std::is_array<T>::value)> {};
79
82 template <typename T>
84 : public std::integral_constant<
85 bool,
86 (is_compliant_base<T>::value &&
87
88 // Must be copy constructible to allow cloning the pointee.
89 PointeeManager::is_copy_constructible<T>::value)> {};
90
93 template <typename T>
94 using is_defaultable = PtrInternal::DefaultPtrTraits::is_defaultable<T>;
95};
96
97//==============================================================================
98// CLASS PtrDefaultFlag
99//==============================================================================
100
125
126//==============================================================================
127// CLASS Ptr
128//==============================================================================
129
197
206template <class T>
207class Ptr : private PtrInternal::PtrRep<T> {
208private:
209 // NOLINTNEXTLINE(modernize-unary-static-assert)
211
212 /*----- types -----*/
214 using PtrRep = PtrInternal::PtrRep<T>;
215
224 template <class Y>
225 using if_convertible_from =
226 typename std::enable_if<std::is_convertible<Y*, T*>::value>::type;
227
232 template <class Y>
233 using if_compliant_and_convertible_from = typename std::enable_if<
234 std::is_convertible<Y*, T*>::value &&
236
237public:
238 /*----- types -----*/
239
241 using element_type = T;
242
245 typename std::add_lvalue_reference<const element_type>::type;
246
248 using use_count_type = std::intptr_t;
249
250 /*----- member functions -----*/
251
253
259 constexpr Ptr() noexcept;
260 // NOLINTNEXTLINE(google-explicit-constructor)
261 constexpr Ptr(std::nullptr_t) noexcept;
263
267
269
286 template <class Y, class = if_compliant_and_convertible_from<Y>>
287 explicit Ptr(Y* p);
288
306 template <class Y, class D, class = if_compliant_and_convertible_from<Y>>
307 Ptr(Y* p, D d);
309
311
323 template <class D>
324 Ptr(std::nullptr_t, D d);
326
328
339 Ptr(Ptr const& rhs) noexcept;
340
353 template <class Y, class = if_convertible_from<Y>>
354 // NOLINTNEXTLINE(google-explicit-constructor)
355 Ptr(Ptr<Y> const& rhs) noexcept;
357
359
367 Ptr(Ptr&& rhs) noexcept;
368
378 template <class Y, class = if_convertible_from<Y>>
379 // NOLINTNEXTLINE(google-explicit-constructor)
380 Ptr(Ptr<Y>&& rhs) noexcept;
381
391 template <class Y, class = if_convertible_from<Y>>
392 // NOLINTNEXTLINE(google-explicit-constructor)
393 Ptr(MutablePtr<Y> rhs) noexcept;
395
397
410 ~Ptr();
412
414
426 Ptr& operator=(Ptr const& rhs) noexcept;
427
438 template <class Y, class = if_convertible_from<Y>>
439 Ptr& operator=(Ptr<Y> const& rhs) noexcept;
441
443
454 Ptr& operator=(Ptr&& rhs) noexcept;
455
468 template <class Y, class = if_convertible_from<Y>>
469 Ptr& operator=(Ptr<Y>&& rhs) noexcept;
470
481 template <class Y, class = if_convertible_from<Y>>
482 Ptr& operator=(MutablePtr<Y> rhs) noexcept;
484
487
493 void swap(Ptr& rhs) noexcept;
494
501 void reset() noexcept;
502
515 template <class Y, class = if_compliant_and_convertible_from<Y>>
516 void reset(Y* p);
517
532 template <class Y, class D, class = if_compliant_and_convertible_from<Y>>
533 void reset(Y* p, D d);
534
562
588 template <typename Func>
589 void mutate(Func&& func);
591
593
599 element_const_reference_type operator*() const noexcept;
600
605 element_type const* operator->() const noexcept;
606
610 element_type const* get() const noexcept;
611
615 bool unique() const noexcept;
616
630 use_count_type use_count() const noexcept;
631
635 explicit operator bool() const noexcept;
636
648 template <class Y>
649 bool owner_before(Ptr<Y> const& rhs) const noexcept;
651
652protected:
653 /*----- member functions -----*/
654
656
676 Ptr(T* p, PtrInternal::PtrCntrlBlk* cntrlBlk, bool doIncUseCount);
679
680 using PtrRep::getPointee;
681
682private:
685 template <class Y>
686 friend class Ptr;
687
690 template <class Y>
691 friend class PtrGuard;
692
695 friend struct Internal::PtrCast;
696};
697
699template <typename T>
701
702//==============================================================================
703// CLASS MutablePtr
704//==============================================================================
705
760template <typename T>
761class MutablePtr : private Ptr<T> {
762private:
763 // NOLINTNEXTLINE(modernize-unary-static-assert)
765
766 /*----- types -----*/
767
769 using Base = Ptr<T>;
770
772 template <class Y>
773 using if_convertible_from =
774 typename std::enable_if<std::is_convertible<Y*, T*>::value>::type;
775
776public:
777 /*----- types -----*/
778
781
782 /*----- member functions -----*/
783
785
790 constexpr MutablePtr() noexcept = default;
791 // NOLINTNEXTLINE(google-explicit-constructor)
792 constexpr MutablePtr(std::nullptr_t) noexcept;
794
796 // NOLINTNEXTLINE(google-explicit-constructor)
797 MutablePtr(T* p);
798
800 MutablePtr(MutablePtr&&) noexcept = default;
801
803 MutablePtr(MutablePtr const&) noexcept = delete;
804
807 template <class Y, class = if_convertible_from<Y>>
808 // NOLINTNEXTLINE(google-explicit-constructor)
809 MutablePtr(MutablePtr<Y> rhs) noexcept;
810
812 ~MutablePtr();
813
815 MutablePtr& operator=(MutablePtr&&) noexcept = default;
816
818 MutablePtr& operator=(MutablePtr const&) noexcept = delete;
819
822 template <class Y, class = if_convertible_from<Y>>
823 MutablePtr& operator=(MutablePtr<Y> rhs) noexcept;
824
828 // clang-format off
829 T const& operator*() const noexcept { assert(get()); return *get(); }
830 T& operator*() noexcept { assert(get()); return *get(); }
831
833 T const* operator->() const noexcept { assert(get()); return get(); }
834 T* operator->() noexcept { assert(get()); return get(); }
835 // clang-format on
836
838 T const* get() const noexcept { return Base::get(); }
839 T* get() noexcept { return Base::getPointee(); }
841
845 explicit operator bool() const { return Base::operator bool(); }
846
848 void reset() { Base::reset(); }
849
851 void swap(MutablePtr& rhs) noexcept;
852
876 Ptr<T> toImmutable() noexcept;
877
878private:
883 MutablePtr(T* p, PtrInternal::PtrCntrlBlk* cntrlBlk)
884 : Base(p, cntrlBlk, /*doIncUseCount=*/false) {
885 assert(Base::unique());
886 }
887
888#ifndef NDEBUG
890 bool unique_or_null() const { return !*this || Base::unique(); }
891#endif
892
895 template <typename Y>
896 friend class Ptr;
897
898 template <typename Y>
899 friend class MutablePtr;
900
901 template <typename Y>
902 friend class PtrGuard;
903};
904
905//==============================================================================
906// CLASS PtrGuardUniqueFlag
907//==============================================================================
908
919
920//==============================================================================
921// CLASS PtrGuard
922//==============================================================================
923
956template <typename T>
957class PtrGuard {
958private:
959 /*----- types -----*/
960
962 template <typename Y>
963 using if_convertible_from =
964 typename std::enable_if<std::is_convertible<Y*, T*>::value>::type;
965
966public:
971 explicit PtrGuard(Ptr<T>& src);
974 explicit PtrGuard(Ptr<T>& src, PtrGuardUniqueFlag);
975
980 template <class Y, class = if_convertible_from<Y>>
981 explicit PtrGuard(Ptr<Y>& src);
982
988 PtrGuard(PtrGuard&&) noexcept = default;
989
991 PtrGuard(PtrGuard const&) noexcept = delete;
992
996 PtrGuard& operator=(PtrGuard&&) noexcept = delete;
997
999 PtrGuard& operator=(PtrGuard const&) noexcept = delete;
1000
1005 ~PtrGuard();
1006
1008 T& operator*() { return *m_ptr; }
1009
1011 T* operator->() { return m_ptr.operator->(); }
1012
1014 const T& operator*() const { return *m_ptr; }
1015
1017 const T* operator->() const { return m_ptr.operator->(); }
1018
1019private:
1021 Ptr<T>* m_src = nullptr;
1022
1024 MutablePtr<T> m_ptr;
1025};
1026
1029template <typename T>
1031template <typename T>
1034
1035//==============================================================================
1036// CLASS Ptr
1037//==============================================================================
1038
1039//------------------------------------------------------------------------------
1040//
1041template <class T>
1042inline constexpr Ptr<T>::Ptr() noexcept : PtrRep(nullptr) {}
1043
1044//------------------------------------------------------------------------------
1045//
1046template <class T>
1047inline constexpr Ptr<T>::Ptr(std::nullptr_t) noexcept : PtrRep(nullptr) {}
1048
1049//------------------------------------------------------------------------------
1050//
1051template <class T>
1052template <class Y, class>
1053inline Ptr<T>::Ptr(Y* p) : PtrRep(PtrInternal::kUninitialized) {
1054 // The control block must dispose of the pointer using its
1055 // original type, i.e Y, not T!!!
1056 using NonConstY = typename std::remove_cv<Y>::type;
1057 auto nonConstP = const_cast<NonConstY*>(p);
1058 this->template init_dispatch<NonConstY>(nonConstP);
1059
1060 // FIXME: In theory, we have to delete "p" if the previous allocation fails.
1061}
1062
1063//------------------------------------------------------------------------------
1064//
1065template <class T>
1066template <class Y, class D, class>
1067inline Ptr<T>::Ptr(Y* p, D d) : PtrRep(PtrInternal::kUninitialized) {
1068 // The control block must dispose of the pointer using its
1069 // original type, i.e Y, not T!!!
1070 this->init(p, new PtrInternal::PtrCntrlBlkPtrDel<Y, D>(p, d));
1071
1072 // FIXME: In theory, we have to delete "p" if the previous allocation fails.
1073}
1074
1075//------------------------------------------------------------------------------
1076//
1077template <class T>
1078template <class D>
1079inline Ptr<T>::Ptr(std::nullptr_t, D d) : PtrRep(PtrInternal::kUninitialized) {
1080 this->init(nullptr, new PtrInternal::PtrCntrlBlkPtrDel<T, D>(nullptr, d));
1081
1082 // FIXME: In theory, we have to delete "p" if the previous allocation fails.
1083}
1084
1085//------------------------------------------------------------------------------
1086//
1088template <class T>
1089inline Ptr<T>::Ptr(T* p, PtrInternal::PtrCntrlBlk* cntrlBlk, bool doIncUseCount)
1090 : PtrRep(p, cntrlBlk) {
1091 if (doIncUseCount) this->incUseCount();
1092}
1094
1095//------------------------------------------------------------------------------
1096//
1097template <class T>
1098inline Ptr<T>::Ptr(Ptr const& rhs) noexcept
1099 : PtrRep(rhs.getPointee(), rhs.getCntrlBlk()) {
1100 this->incUseCount();
1101}
1102
1103//------------------------------------------------------------------------------
1104//
1105template <class T>
1106template <class Y, class>
1107inline Ptr<T>::Ptr(Ptr<Y> const& rhs) noexcept
1108 : PtrRep(rhs.getPointee(), rhs.getCntrlBlk()) {
1109 this->incUseCount();
1110}
1111
1112//------------------------------------------------------------------------------
1113//
1114template <class T>
1115inline Ptr<T>::Ptr(Ptr&& rhs) noexcept
1116 : PtrRep(rhs.getPointee(), rhs.getCntrlBlk()) {
1117 rhs.init(nullptr, nullptr);
1118}
1119
1120//------------------------------------------------------------------------------
1121//
1122template <class T>
1123template <class Y, class>
1124inline Ptr<T>::Ptr(Ptr<Y>&& rhs) noexcept
1125 : PtrRep(rhs.getPointee(), rhs.getCntrlBlk()) {
1126 rhs.init(nullptr, nullptr);
1127}
1128
1129//------------------------------------------------------------------------------
1130//
1131template <class T>
1132template <class Y, class>
1133inline Ptr<T>::Ptr(MutablePtr<Y> rhs) noexcept
1134 : PtrRep(rhs.getPointee(), rhs.getCntrlBlk()) {
1135 rhs.init(nullptr, nullptr);
1136 assert(!rhs.getPointee() || unique());
1137}
1138
1139//------------------------------------------------------------------------------
1140//
1141template <class T>
1142inline Ptr<T>::~Ptr() = default;
1143
1144//------------------------------------------------------------------------------
1145//
1146template <class T>
1147inline Ptr<T>& Ptr<T>::operator=(Ptr const& rhs) noexcept {
1148 this->PtrRep::operator=(rhs);
1149 return *this;
1150}
1151
1152//------------------------------------------------------------------------------
1153//
1154template <class T>
1155template <class Y, class>
1156inline Ptr<T>& Ptr<T>::operator=(Ptr<Y> const& rhs) noexcept {
1157 this->PtrRep::operator=(Ptr(rhs));
1158 return *this;
1159}
1160
1161//------------------------------------------------------------------------------
1162//
1163template <class T>
1164inline Ptr<T>& Ptr<T>::operator=(Ptr&& rhs) noexcept {
1165 this->PtrRep::operator=(std::move(rhs));
1166 return *this;
1167}
1168
1169//------------------------------------------------------------------------------
1170//
1171template <class T>
1172template <class Y, class>
1173inline Ptr<T>& Ptr<T>::operator=(Ptr<Y>&& rhs) noexcept {
1174 this->PtrRep::operator=(Ptr(std::move(rhs)));
1175 return *this;
1176}
1177
1178//------------------------------------------------------------------------------
1179//
1180template <class T>
1181template <class Y, class>
1183 this->PtrRep::operator=(Ptr<T>(std::move(rhs)));
1184 return *this;
1185}
1186
1187//------------------------------------------------------------------------------
1188//
1189template <class T>
1190inline void Ptr<T>::swap(Ptr& rhs) noexcept {
1191 PtrRep::swap(rhs);
1192}
1193
1194//------------------------------------------------------------------------------
1195//
1196template <class T>
1197inline void Ptr<T>::reset() noexcept {
1198 this->operator=(Ptr());
1199}
1200
1201//------------------------------------------------------------------------------
1202//
1203template <class T>
1204template <class Y, class>
1205inline void Ptr<T>::reset(Y* p) {
1206 this->operator=(Ptr(p));
1207}
1208
1209//------------------------------------------------------------------------------
1210//
1211template <class T>
1212template <class Y, class D, class>
1213inline void Ptr<T>::reset(Y* p, D d) {
1214 this->operator=(Ptr(p, d));
1215}
1216
1217//------------------------------------------------------------------------------
1218//
1219template <class T>
1221 auto p = const_cast<element_type*>(this->getPointee());
1222 if (!p) {
1223 return MutablePtr<element_type>();
1224 } else {
1225 // Move the pointer...
1226 auto cntrl = this->getCntrlBlk();
1227 if (unique()) {
1228 // Simply move-const-cast the pointer...
1229 this->init(nullptr, nullptr);
1230 return MutablePtr<element_type>(p, cntrl);
1231 } else {
1232 // Non-unique owner, take a copy using the clone operation captured
1233 // at type erasure time!
1234 auto cloned = cntrl->clonePointee(p);
1235 reset();
1237 static_cast<element_type*>(cloned.m_pointee),
1238 cloned.getCntrlBlk());
1239 }
1240 }
1241}
1242
1243//------------------------------------------------------------------------------
1244//
1245template <class T>
1246template <typename Func>
1247void Ptr<T>::mutate(Func&& func) {
1248 assert(unique());
1249
1250 Ptr<T> o = std::move(*this);
1251
1252 auto ptee =
1253 o.unique() ? const_cast<element_type*>(o.getPointee()) : nullptr;
1254 assert(ptee);
1255 func(ptee);
1256
1257 *this = std::move(o);
1258 assert(unique());
1259}
1260
1261//------------------------------------------------------------------------------
1262//
1263template <class T>
1265 const noexcept {
1266 assert(this->getPointee());
1267 return *this->getPointee();
1268}
1269
1270//------------------------------------------------------------------------------
1271//
1272template <class T>
1274 const noexcept {
1275 assert(this->getPointee());
1276 return this->getPointee();
1277}
1278
1279//------------------------------------------------------------------------------
1280//
1281template <class T>
1282inline typename Ptr<T>::element_type const* Ptr<T>::get() const noexcept {
1283 return this->getPointee();
1284}
1285
1286//------------------------------------------------------------------------------
1287//
1288template <class T>
1289inline typename Ptr<T>::use_count_type Ptr<T>::use_count() const noexcept {
1290 auto cblk = this->getCntrlBlk();
1291 return cblk ? cblk->use_count() : 0;
1292}
1293
1294//------------------------------------------------------------------------------
1295//
1296template <class T>
1297inline bool Ptr<T>::unique() const noexcept {
1298 return use_count() == 1;
1299}
1300
1301//------------------------------------------------------------------------------
1302//
1303template <class T>
1304inline Ptr<T>::operator bool() const noexcept {
1305 return this->getPointee() != nullptr;
1306}
1307
1308//------------------------------------------------------------------------------
1309//
1310template <class T>
1311template <class Y>
1312inline bool Ptr<T>::owner_before(Ptr<Y> const& rhs) const noexcept {
1313 return (this->getCntrlBlk() < rhs.getCntrlBlk());
1314}
1315
1316//==============================================================================
1317// CLASS MutablePtr
1318//==============================================================================
1319
1320//------------------------------------------------------------------------------
1321//
1322template <typename T>
1323inline constexpr MutablePtr<T>::MutablePtr(std::nullptr_t) noexcept
1324 : Base(nullptr) {}
1325
1326//------------------------------------------------------------------------------
1327//
1328template <typename T>
1330 assert(unique_or_null());
1331}
1332
1333//------------------------------------------------------------------------------
1334//
1335template <typename T>
1336template <class Y, class>
1338 : Base(std::move(rhs)) {
1339 assert(unique_or_null());
1340}
1341
1342//------------------------------------------------------------------------------
1343//
1344template <typename T>
1346 assert(unique_or_null());
1347}
1348
1349//------------------------------------------------------------------------------
1350//
1351template <typename T>
1352template <class Y, class>
1354 Base::operator=(std::move(rhs));
1355 assert(unique_or_null());
1356 return *this;
1357}
1358
1359//------------------------------------------------------------------------------
1360//
1361template <typename T>
1362void MutablePtr<T>::swap(MutablePtr& rhs) noexcept {
1363 Base::swap(rhs);
1364}
1365
1366//------------------------------------------------------------------------------
1367//
1368template <typename T>
1370 Amino::Ptr<T> o;
1371 o.swap(*this);
1372 return o;
1373}
1374
1375//==============================================================================
1376// CLASS PtrGuard
1377//==============================================================================
1378
1379template <typename T>
1381 : m_src(&src), m_ptr(src.toMutable()) {
1382 assert(!*m_src);
1383}
1384template <typename T>
1386 : m_src(&src), m_ptr(src.getPointee(), src.getCntrlBlk()) {
1387 m_src->init(nullptr, nullptr);
1388 assert(!*m_src);
1389 assert(m_ptr.unique_or_null());
1390}
1391template <typename T>
1392template <class Y, class>
1394 : m_src(&reinterpret_cast<Ptr<T>&>(src)), m_ptr(src.toMutable()) {
1395 assert(!*m_src);
1396}
1397template <typename T>
1399 if (!m_ptr) return;
1400 assert(!*m_src);
1401 *m_src = m_ptr.toImmutable();
1402}
1403
1404//==============================================================================
1405// GLOBAL FUNCTIONS CLASS Amino::Ptr
1406//==============================================================================
1407
1409
1411
1418
1419//------------------------------------------------------------------------------
1420//
1421template <class T, class U>
1422inline bool operator==(Ptr<T> const& x, Ptr<U> const& y) noexcept {
1423 return x.get() == y.get();
1424}
1425
1426//------------------------------------------------------------------------------
1427//
1428template <class T>
1429inline bool operator==(const Ptr<T>& x, std::nullptr_t) noexcept {
1430 return !x;
1431}
1432
1433//------------------------------------------------------------------------------
1434//
1435template <class T>
1436inline bool operator==(std::nullptr_t, const Ptr<T>& y) noexcept {
1437 return !y;
1438}
1439
1446
1447//------------------------------------------------------------------------------
1448//
1449template <class T, class U>
1450inline bool operator!=(Ptr<T> const& x, Ptr<U> const& y) noexcept {
1451 return !(x == y);
1452}
1453
1454//------------------------------------------------------------------------------
1455//
1456template <class T>
1457inline bool operator!=(const Ptr<T>& x, std::nullptr_t) noexcept {
1458 return static_cast<bool>(x);
1459}
1460
1461//------------------------------------------------------------------------------
1462//
1463template <class T>
1464inline bool operator!=(std::nullptr_t, const Ptr<T>& y) noexcept {
1465 return static_cast<bool>(y);
1466}
1468
1470
1472
1481
1482//------------------------------------------------------------------------------
1483//
1484template <class T, class U>
1485inline bool operator<(Ptr<T> const& x, Ptr<U> const& y) noexcept {
1486 using VP = typename std::common_type<T*, U*>::type;
1487 using V = typename std::remove_pointer<VP>::type;
1488
1489 return std::less<V const*>()(x.get(), y.get());
1490}
1491
1492//------------------------------------------------------------------------------
1493//
1494template <class T>
1495inline bool operator<(const Ptr<T>& x, std::nullptr_t) noexcept {
1496 return std::less<T const*>()(x.get(), nullptr);
1497}
1498
1499//------------------------------------------------------------------------------
1500//
1501template <class T>
1502inline bool operator<(std::nullptr_t, const Ptr<T>& y) noexcept {
1503 return std::less<T const*>()(nullptr, y.get());
1504}
1505
1514
1515//------------------------------------------------------------------------------
1516//
1517template <class T, class U>
1518inline bool operator>(Ptr<T> const& x, Ptr<U> const& y) noexcept {
1519 return (y < x);
1520}
1521
1522//------------------------------------------------------------------------------
1523//
1524template <class T>
1525inline bool operator>(const Ptr<T>& x, std::nullptr_t) noexcept {
1526 return (nullptr < x);
1527}
1528
1529//------------------------------------------------------------------------------
1530//
1531template <class T>
1532inline bool operator>(std::nullptr_t, const Ptr<T>& y) noexcept {
1533 return (y < nullptr);
1534}
1535
1544
1545//------------------------------------------------------------------------------
1546//
1547template <class T, class U>
1548inline bool operator<=(Ptr<T> const& x, Ptr<U> const& y) noexcept {
1549 return !(y < x);
1550}
1551
1552//------------------------------------------------------------------------------
1553//
1554template <class T>
1555inline bool operator<=(const Ptr<T>& x, std::nullptr_t) noexcept {
1556 return !(nullptr < x);
1557}
1558
1559//------------------------------------------------------------------------------
1560//
1561template <class T>
1562inline bool operator<=(std::nullptr_t, const Ptr<T>& y) noexcept {
1563 return !(y < nullptr);
1564}
1565
1574
1575//------------------------------------------------------------------------------
1576//
1577template <class T, class U>
1578inline bool operator>=(Ptr<T> const& x, Ptr<U> const& y) noexcept {
1579 return !(x < y);
1580}
1581
1582//------------------------------------------------------------------------------
1583//
1584template <class T>
1585inline bool operator>=(const Ptr<T>& x, std::nullptr_t) noexcept {
1586 return !(x < nullptr);
1587}
1588
1589//------------------------------------------------------------------------------
1590//
1591template <class T>
1592inline bool operator>=(std::nullptr_t, const Ptr<T>& y) noexcept {
1593 return !(nullptr < y);
1594}
1596
1597//------------------------------------------------------------------------------
1598//
1605template <class T>
1606inline void swap(Ptr<T>& lhs, Ptr<T>& rhs) noexcept {
1607 lhs.swap(rhs);
1608}
1609
1610//==============================================================================
1611// GLOBAL FUNCTIONS CLASS Amino::MutablePtr
1612//==============================================================================
1613
1615
1619
1620//------------------------------------------------------------------------------
1621//
1622template <class T, class U>
1623inline bool operator==(
1624 MutablePtr<T> const& x, MutablePtr<U> const& y) noexcept {
1625 assert(x.get() != y.get() || &x == &y);
1626 return x.get() == y.get();
1627}
1628
1629//------------------------------------------------------------------------------
1630//
1631template <class T>
1632inline bool operator==(const MutablePtr<T>& x, std::nullptr_t) noexcept {
1633 return !x;
1634}
1635
1636//------------------------------------------------------------------------------
1637//
1638template <class T>
1639inline bool operator==(std::nullptr_t, const MutablePtr<T>& y) noexcept {
1640 return !y;
1641}
1642
1645
1646//------------------------------------------------------------------------------
1647//
1648template <class T, class U>
1649inline bool operator!=(
1650 MutablePtr<T> const& x, MutablePtr<U> const& y) noexcept {
1651 return !(x == y);
1652}
1653
1654//------------------------------------------------------------------------------
1655//
1656template <class T>
1657inline bool operator!=(const MutablePtr<T>& x, std::nullptr_t) noexcept {
1658 return static_cast<bool>(x);
1659}
1660
1661//------------------------------------------------------------------------------
1662//
1663template <class T>
1664inline bool operator!=(std::nullptr_t, const MutablePtr<T>& y) noexcept {
1665 return static_cast<bool>(y);
1666}
1668
1670
1672
1681
1682//------------------------------------------------------------------------------
1683//
1684template <class T, class U>
1685inline bool operator<(MutablePtr<T> const& x, MutablePtr<U> const& y) noexcept {
1686 using VP = typename std::common_type<T*, U*>::type;
1687 using V = typename std::remove_pointer<VP>::type;
1688
1689 return std::less<V const*>()(x.get(), y.get());
1690}
1691
1692//------------------------------------------------------------------------------
1693//
1694template <class T>
1695inline bool operator<(const MutablePtr<T>& x, std::nullptr_t) noexcept {
1696 return std::less<T const*>()(x.get(), nullptr);
1697}
1698
1699//------------------------------------------------------------------------------
1700//
1701template <class T>
1702inline bool operator<(std::nullptr_t, const MutablePtr<T>& y) noexcept {
1703 return std::less<T const*>()(nullptr, y.get());
1704}
1705
1714
1715//------------------------------------------------------------------------------
1716//
1717template <class T, class U>
1718inline bool operator>(MutablePtr<T> const& x, MutablePtr<U> const& y) noexcept {
1719 return (y < x);
1720}
1721
1722//------------------------------------------------------------------------------
1723//
1724template <class T>
1725inline bool operator>(const MutablePtr<T>& x, std::nullptr_t) noexcept {
1726 return (nullptr < x);
1727}
1728
1729//------------------------------------------------------------------------------
1730//
1731template <class T>
1732inline bool operator>(std::nullptr_t, const MutablePtr<T>& y) noexcept {
1733 return (y < nullptr);
1734}
1735
1744
1745//------------------------------------------------------------------------------
1746//
1747template <class T, class U>
1748inline bool operator<=(
1749 MutablePtr<T> const& x, MutablePtr<U> const& y) noexcept {
1750 return !(y < x);
1751}
1752
1753//------------------------------------------------------------------------------
1754//
1755template <class T>
1756inline bool operator<=(const MutablePtr<T>& x, std::nullptr_t) noexcept {
1757 return !(nullptr < x);
1758}
1759
1760//------------------------------------------------------------------------------
1761//
1762template <class T>
1763inline bool operator<=(std::nullptr_t, const MutablePtr<T>& y) noexcept {
1764 return !(y < nullptr);
1765}
1766
1775
1776//------------------------------------------------------------------------------
1777//
1778template <class T, class U>
1779inline bool operator>=(
1780 MutablePtr<T> const& x, MutablePtr<U> const& y) noexcept {
1781 return !(x < y);
1782}
1783
1784//------------------------------------------------------------------------------
1785//
1786template <class T>
1787inline bool operator>=(const MutablePtr<T>& x, std::nullptr_t) noexcept {
1788 return !(x < nullptr);
1789}
1790
1791//------------------------------------------------------------------------------
1792//
1793template <class T>
1794inline bool operator>=(std::nullptr_t, const MutablePtr<T>& y) noexcept {
1795 return !(nullptr < y);
1796}
1798
1799//------------------------------------------------------------------------------
1800//
1807template <class T>
1808inline void swap(MutablePtr<T>& lhs, MutablePtr<T>& rhs) noexcept {
1809 lhs.swap(rhs);
1810}
1811
1814
1815//==============================================================================
1816// GLOBAL CASTING FUNCTIONS
1817//==============================================================================
1818
1831template <class T, class U>
1832inline Ptr<T> static_pointer_cast(Ptr<U> const& ptr) noexcept;
1833template <class T, class U>
1834inline Ptr<T> static_pointer_cast(Ptr<U>&& ptr) noexcept;
1836
1837//------------------------------------------------------------------------------
1838//
1851template <class T, class U>
1852inline Ptr<T> dynamic_pointer_cast(Ptr<U> const& ptr) noexcept;
1853template <class T, class U>
1854inline Ptr<T> dynamic_pointer_cast(Ptr<U>&& ptr) noexcept;
1857
1858//==============================================================================
1859// FUNCTION makeDefaultPtr
1860//==============================================================================
1861
1866template <typename T>
1867std::enable_if_t<
1868 PtrInternal::DefaultPtrTraits::has_default_class<T>::value,
1869 Ptr<T>>
1871 return Internal::getDefaultClass<T>();
1872}
1873template <typename T>
1874std::enable_if_t<PtrInternal::DefaultPtrTraits::is_array<T>::value, Ptr<T>>
1876 return Ptr<T>(PointeeManager::newClass<T>());
1877}
1878template <typename T>
1879std::enable_if_t<
1880 !PtrInternal::DefaultPtrTraits::is_defaultable<T>::value,
1881 Ptr<T>>
1883 // This static_assert will always fail when makeDefaultPtr resolves to this
1884 // overload, indicating what needs to be done to fix the compile error.
1885 static_assert(
1886 PtrInternal::DefaultPtrTraits::has_default_class<T>::value,
1887 "Missing default class getter for class T. See "
1888 "AMINO_DECLARE_DEFAULT_CLASS in <Amino/Cpp/ClassDeclare.h> and "
1889 "AMINO_DEFINE_DEFAULT_CLASS in <Amino/Cpp/ClassDefine.h>");
1890 return nullptr;
1891}
1893
1894//------------------------------------------------------------------------------
1895// This ctor has to be defined after makeDefaultPtr() since it uses it.
1896template <class T>
1898
1899//==============================================================================
1900// FUNCTION newClassPtr
1901//==============================================================================
1902
1912template <class T, class... Args>
1913inline Ptr<T> newClassPtr(Args&&... args) {
1914 static_assert(
1916 "The class of type T cannot be stored in an Amino::Ptr<T>");
1917 return Ptr<T>(PointeeManager::newClass<T>(std::forward<Args>(args)...));
1918}
1919
1939template <class T, class E>
1940inline Ptr<T> newClassPtr(std::initializer_list<E> list) {
1941 static_assert(
1943 "The class of type T cannot be stored in an Amino::Ptr<T>");
1944 return Ptr<T>(PointeeManager::newClass<T>(std::move(list)));
1945}
1946
1947//==============================================================================
1948// FUNCTION newMutablePtr
1949//==============================================================================
1950
1961template <class T, class... Args>
1962inline MutablePtr<T> newMutablePtr(Args&&... args) {
1963 static_assert(
1965 "The class of type T cannot be stored in an Amino::MutablePtr<T>");
1966 return MutablePtr<T>(
1967 PointeeManager::newClass<T>(std::forward<Args>(args)...));
1968}
1969
1989template <class T, class E>
1990inline MutablePtr<T> newMutablePtr(std::initializer_list<E> list) {
1991 static_assert(
1993 "The class of type T cannot be stored in an Amino::MutablePtr<T>");
1994 return MutablePtr<T>(PointeeManager::newClass<T>(std::move(list)));
1995}
1996
2001template <typename T>
2003 return PtrGuard{src};
2004}
2005template <typename T1, typename T2>
2007 return PtrGuard<T1>(src);
2008}
2009template <typename T>
2011 return PtrGuard{src, PtrGuardUniqueFlag{}};
2012}
2014
2015//==============================================================================
2016// PTR CAST IMPLEMENTATIONS
2017//==============================================================================
2018
2019namespace Internal {
2020struct PtrCast {
2021 template <class T, class U>
2022 static inline Ptr<T> static_pointer_cast(Ptr<U> const& ptr) noexcept {
2023 T* p = static_cast<T*>(ptr.getPointee());
2024 return Ptr<T>(p, ptr.getCntrlBlk(), true);
2025 }
2026 template <class T, class U>
2027 static inline Ptr<T> static_pointer_cast(Ptr<U>&& ptr) noexcept {
2028 T* p = static_cast<T*>(ptr.getPointee());
2029 auto ret = Ptr<T>(p, ptr.getCntrlBlk(), false);
2030 ptr.init(nullptr, nullptr);
2031 return ret;
2032 }
2033 template <class T, class U>
2034 static inline Ptr<T> dynamic_pointer_cast(Ptr<U> const& ptr) noexcept {
2035 T* p = dynamic_cast<T*>(ptr.getPointee());
2036 if (!p) return Ptr<T>{};
2037 return Ptr<T>(p, ptr.getCntrlBlk(), true);
2038 }
2039 template <class T, class U>
2040 static inline Ptr<T> dynamic_pointer_cast(Ptr<U>&& ptr) noexcept {
2041 T* p = dynamic_cast<T*>(ptr.getPointee());
2042 if (!p) {
2043 ptr.reset();
2044 return Ptr<T>{};
2045 }
2046 auto ret = Ptr<T>(p, ptr.getCntrlBlk(), false);
2047 ptr.init(nullptr, nullptr);
2048 return ret;
2049 }
2050};
2051} // namespace Internal
2052
2053//------------------------------------------------------------------------------
2054//
2055template <class T, class U>
2056inline Ptr<T> static_pointer_cast(Ptr<U> const& ptr) noexcept {
2057 return Internal::PtrCast::static_pointer_cast<T>(ptr);
2058}
2059template <class T, class U>
2060inline Ptr<T> static_pointer_cast(Ptr<U>&& ptr) noexcept {
2061 return Internal::PtrCast::static_pointer_cast<T>(std::move(ptr));
2062}
2063
2064//------------------------------------------------------------------------------
2065//
2066template <class T, class U>
2067inline Ptr<T> dynamic_pointer_cast(Ptr<U> const& ptr) noexcept {
2068 return Internal::PtrCast::dynamic_pointer_cast<T>(ptr);
2069}
2070template <class T, class U>
2071inline Ptr<T> dynamic_pointer_cast(Ptr<U>&& ptr) noexcept {
2072 return Internal::PtrCast::dynamic_pointer_cast<T>(std::move(ptr));
2073}
2074} // namespace Amino
2075
2076//==============================================================================
2077// std::hash< Amino::Ptr<T> >
2078//==============================================================================
2079
2080namespace std {
2081
2090template <class T>
2091struct hash<Amino::Ptr<T>> {
2093 using result_type = size_t;
2094
2095 result_type operator()(const argument_type& ptr) const noexcept {
2096 return hash<T const*>()(ptr.get());
2097 }
2098};
2099} // namespace std
2100
2101#endif
Amino::Ptr's forward declarations.
Definition: HostData.h:33
Ptr< T > newClassPtr(Args &&... args)
Creates a Ptr holding a new T constructed from the given arguments.
Definition: Ptr.h:1913
Ptr(MutablePtr< T >) -> Ptr< T >
Deduction guide for Ptr.
bool operator<(Ptr< T > const &x, Ptr< U > const &y) noexcept
Compares the pointer values.
Definition: Ptr.h:1485
Ptr< T > dynamic_pointer_cast(Ptr< U > const &ptr) noexcept
Dynamic pointer cast.
Definition: Ptr.h:2067
PtrGuard< T > createPtrGuard(Ptr< T > &src)
Create a PtrGuard for the given Ptr.
Definition: Ptr.h:2002
bool operator>(Ptr< T > const &x, Ptr< U > const &y) noexcept
Compares the pointer values.
Definition: Ptr.h:1518
void swap(MutablePtr< T > &lhs, MutablePtr< T > &rhs) noexcept
Swap two pointers.
Definition: Ptr.h:1808
Ptr< T > static_pointer_cast(Ptr< U > const &ptr) noexcept
Static pointer cast.
Definition: Ptr.h:2056
bool operator==(Ptr< T > const &x, Ptr< U > const &y) noexcept
Return true if pointers are equal.
Definition: Ptr.h:1422
std::enable_if_t< PtrInternal::DefaultPtrTraits::has_default_class< T >::value, Ptr< T > > makeDefaultPtr()
Creates a Ptr holding the default value for T.
Definition: Ptr.h:1870
bool operator<=(Ptr< T > const &x, Ptr< U > const &y) noexcept
Compares the pointer values.
Definition: Ptr.h:1548
void swap(Any &lhs, Any &rhs) noexcept
Swap the payloads of two instances of Any.
Definition: Any.h:358
bool operator!=(Ptr< T > const &x, Ptr< U > const &y) noexcept
Return true if pointers are not equal.
Definition: Ptr.h:1450
bool operator>=(Ptr< T > const &x, Ptr< U > const &y) noexcept
Compares the pointer values.
Definition: Ptr.h:1578
MutablePtr< T > newMutablePtr(Args &&... args)
Creates a MutablePtr holding a new T constructed from the given arguments.
Definition: Ptr.h:1962
Definition: Ptr.h:2080
Define a Amino array of elements of type T.
Definition: Array.h:105
Traits about the to-be-pointee of an Amino::Ptr<T> or Amino::MutablePtr<T> class.
Definition: Ptr.h:54
PtrInternal::DefaultPtrTraits::is_defaultable< T > is_defaultable
Whether Ptr{PtrDefaultFlag{}} or Amino::makeDefaultPtr<T>() can be used for a pointee of type T.
Definition: Ptr.h:94
Whether a Ptr<T> or MutablePtr<T> can be instantiated.
Definition: Ptr.h:78
Whether the class of type T can be stored in an Amino::Ptr<T> or an Amino::MutablePtr<T>.
Definition: Ptr.h:89
Flag that may be passed when creating a Ptr, to make it contain a default value as its pointee.
Definition: Ptr.h:124
Smart pointers allowing custom user classes (opaque classes) to be used within Amino graphs.
Definition: Ptr.h:207
void reset() noexcept
Reset the pointer to an empty pointer.
Definition: Ptr.h:1197
Ptr & operator=(Ptr const &rhs) noexcept
Assignment operator.
Definition: Ptr.h:1147
typename std::add_lvalue_reference< const element_type >::type element_const_reference_type
A reference to a const element_type.
Definition: Ptr.h:245
void mutate(Func &&func)
Definition: Ptr.h:1247
element_type const * operator->() const noexcept
Indirection.
Definition: Ptr.h:1273
~Ptr()
Destructor.
bool owner_before(Ptr< Y > const &rhs) const noexcept
Owner-based ordering of Ptr.
Definition: Ptr.h:1312
MutablePtr< element_type > toMutable() noexcept
Conversion to MutablePtr.
Definition: Ptr.h:1220
void swap(Ptr &rhs) noexcept
Swap two pointers.
Definition: Ptr.h:1190
constexpr Ptr() noexcept
Construct an empty pointer.
Definition: Ptr.h:1042
element_const_reference_type operator*() const noexcept
Indirection.
Definition: Ptr.h:1264
std::intptr_t use_count_type
The integral type of the use count.
Definition: Ptr.h:248
friend class Ptr
Friendship to allow conversion between pointers of different types.
Definition: Ptr.h:686
T element_type
The type of objects referenced by the Ptr pointer.
Definition: Ptr.h:241
use_count_type use_count() const noexcept
Returns the use count of the pointed object.
Definition: Ptr.h:1289
bool unique() const noexcept
Returns whether the object is uniquely owned by the pointer.
Definition: Ptr.h:1297
friend class PtrGuard
Friendship to allow access to getPointee, getCtrlBlck, and init. Used when the guard is created with ...
Definition: Ptr.h:691
element_type const * get() const noexcept
Accessor.
Definition: Ptr.h:1282
Transient version of Amino::Ptr<T> which allows mutable access to the pointee.
Definition: Ptr.h:761
MutablePtr & operator=(MutablePtr &&) noexcept=default
Move assignment.
void reset()
Reset the pointer to an empty pointer.
Definition: Ptr.h:848
Ptr< T > toImmutable() noexcept
Conversion to a Ptr (immutable)
Definition: Ptr.h:1369
T const * operator->() const noexcept
Indirection.
Definition: Ptr.h:833
void swap(MutablePtr &rhs) noexcept
Swap two pointers.
Definition: Ptr.h:1362
constexpr MutablePtr() noexcept=default
Construct an empty MutablePtr.
T const * get() const noexcept
Accessor.
Definition: Ptr.h:838
T * operator->() noexcept
Indirection.
Definition: Ptr.h:834
friend class MutablePtr
Definition: Ptr.h:899
T * get() noexcept
Indirection.
Definition: Ptr.h:839
T & operator*() noexcept
Indirection.
Definition: Ptr.h:830
~MutablePtr()
Destructor.
Definition: Ptr.h:1345
Flag that may be passed when creating a PtrGuard.
Definition: Ptr.h:918
Helper guard to allow mutation on a pointee for the lifescope of the PtrGuard<T> but then reassigning...
Definition: Ptr.h:957
const T * operator->() const
Returns a const pointer to the uniquely owned object.
Definition: Ptr.h:1017
const T & operator*() const
Returns a const reference to the uniquely owned object.
Definition: Ptr.h:1014
~PtrGuard()
Destructor.
Definition: Ptr.h:1398
T * operator->()
Returns a pointer to the uniquely owned object.
Definition: Ptr.h:1011
PtrGuard(PtrGuard &&) noexcept=default
Move constructor.
PtrGuard(Ptr< T > &src)
Constructor.
Definition: Ptr.h:1380
result_type operator()(const argument_type &ptr) const noexcept
Definition: Ptr.h:2095