/
AnySharedPointer.h
144 lines (121 loc) · 3.79 KB
/
AnySharedPointer.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
// Copyright (C) 2012-2015 Leap Motion, Inc. All rights reserved.
#pragma once
#include "auto_id.h"
#include "fast_pointer_cast.h"
/// AnySharedPointer
struct AnySharedPointer {
public:
AnySharedPointer(void) = default;
AnySharedPointer(AnySharedPointer&& rhs);
AnySharedPointer(const AnySharedPointer& rhs) = default;
template<class T>
AnySharedPointer(const std::shared_ptr<T>& rhs) :
m_ti(auto_id_t<T>{}),
m_ptr(rhs)
{}
~AnySharedPointer(void);
protected:
auto_id m_ti;
std::shared_ptr<void> m_ptr;
public:
explicit operator bool(void) const { return (bool)m_ptr; }
void* ptr(void) const { return m_ptr.get(); }
bool empty(void) const { return !m_ptr; }
auto_id type(void) const { return m_ti; }
std::shared_ptr<void>& operator*(void) { return m_ptr; }
const std::shared_ptr<void>& operator*(void) const { return m_ptr; }
void reset(void) {
m_ptr.reset();
}
std::shared_ptr<CoreObject> as_obj(void) const {
return
m_ti.block->pToObj ?
m_ti.block->pToObj(m_ptr) :
nullptr;
}
/// <summary>
/// Attempts to dynamically assign this slot to the specified object without changing the current type
/// </summary>
/// <returns>True if the assignment succeeds</returns>
bool try_assign(const std::shared_ptr<CoreObject>& rhs) {
if (!m_ti.block->pFromObj)
return nullptr;
auto ptr = m_ti.block->pFromObj(rhs);
if (!ptr)
return false;
m_ptr = std::move(ptr);
return true;
}
/// <summary>
/// Attempts to dynamically assign this slot to the specified object without changing the current type
/// </summary>
/// <returns>True if the assignment succeeds</returns>
bool try_assign(const AnySharedPointer& rhs) {
auto obj = rhs.as_obj();
return obj && try_assign(obj);
}
template<class T>
const std::shared_ptr<T>& as(void) const {
// The safety of this routine is verified by the AnySharedPointer unit tests
return *reinterpret_cast<const std::shared_ptr<T>*>(&m_ptr);
}
bool operator==(const AnySharedPointer& rhs) const {
// Need to compare the control blocks, not the pointer values, because we could be pointing to
// different spots in the same object.
return
!m_ptr.owner_before(rhs.m_ptr) &&
!rhs.m_ptr.owner_before(m_ptr);
}
template<typename T>
bool operator==(const std::shared_ptr<T>& rhs) const {
return m_ptr == rhs;
}
bool operator!=(std::nullptr_t) const {
return !!m_ptr;
}
template<typename T>
void init(void) {
m_ti = auto_id_t<T>{};
m_ptr.reset();
}
// Additional operator overloads:
bool operator<(const AnySharedPointer& rhs) const { return m_ptr < rhs.m_ptr;}
bool operator!=(const AnySharedPointer& rhs) const { return !(*this == rhs); }
void operator=(const AnySharedPointer& rhs) {
m_ti = rhs.m_ti;
m_ptr = rhs.m_ptr;
}
/// <summary>
/// Convenience overload for shared pointer assignment
/// </summary>
template<class T>
void operator=(const std::shared_ptr<T>& rhs) {
m_ptr = rhs;
}
};
/// <summary>
/// Convenience implementation of AnySharedPointer which is initially of type T
/// </summary>
/// <remarks>
/// Using this type will automatically ensure that the underlying auto_id is fully instantiated
/// </remarks>
template<class T>
class AnySharedPointerT:
public AnySharedPointer
{
public:
AnySharedPointerT(void):
AnySharedPointer(std::shared_ptr<T>{})
{}
T& operator*(void) { return *as<T>(); }
const T& operator*(void) const { return *as<T>(); }
T* operator->(void) { return as<T>()->get(); }
const T* operator->(void) const { return as<T>()->get(); }
const std::shared_ptr<T>& get(void) const {
return AnySharedPointer::as<T>();
}
};
template<class T>
inline bool operator==(const std::shared_ptr<T>& lhs, const AnySharedPointer& rhs) {
return rhs == lhs;
}