Warning: This file is not a C or C++ file. It does not have highlighting.
1 | //===-- include/flang/Common/indirection.h ----------------------*- C++ -*-===// |
---|---|
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #ifndef FORTRAN_COMMON_INDIRECTION_H_ |
10 | #define FORTRAN_COMMON_INDIRECTION_H_ |
11 | |
12 | // Define a smart pointer class template that is rather like |
13 | // non-nullable std::unique_ptr<>. Indirection<> is, like a C++ reference |
14 | // type, restricted to be non-null when constructed or assigned. |
15 | // Indirection<> optionally supports copy construction and copy assignment. |
16 | // |
17 | // To use Indirection<> with forward-referenced types, add |
18 | // extern template class Fortran::common::Indirection<FORWARD_TYPE>; |
19 | // outside any namespace in a header before use, and |
20 | // template class Fortran::common::Indirection<FORWARD_TYPE>; |
21 | // in one C++ source file later where a definition of the type is visible. |
22 | |
23 | #include "idioms.h" |
24 | #include <memory> |
25 | #include <type_traits> |
26 | #include <utility> |
27 | |
28 | namespace Fortran::common { |
29 | |
30 | // The default case does not support (deep) copy construction or assignment. |
31 | template <typename A, bool COPY = false> class Indirection { |
32 | public: |
33 | using element_type = A; |
34 | Indirection() = delete; |
35 | Indirection(A *&&p) : p_{p} { |
36 | CHECK(p_ && "assigning null pointer to Indirection"); |
37 | p = nullptr; |
38 | } |
39 | Indirection(A &&x) : p_{new A(std::move(x))} {} |
40 | Indirection(Indirection &&that) : p_{that.p_} { |
41 | CHECK(p_ && "move construction of Indirection from null Indirection"); |
42 | that.p_ = nullptr; |
43 | } |
44 | ~Indirection() { |
45 | delete p_; |
46 | p_ = nullptr; |
47 | } |
48 | Indirection &operator=(Indirection &&that) { |
49 | CHECK(that.p_ && "move assignment of null Indirection to Indirection"); |
50 | auto tmp{p_}; |
51 | p_ = that.p_; |
52 | that.p_ = tmp; |
53 | return *this; |
54 | } |
55 | |
56 | A &value() { return *p_; } |
57 | const A &value() const { return *p_; } |
58 | |
59 | bool operator==(const A &that) const { return *p_ == that; } |
60 | bool operator==(const Indirection &that) const { return *p_ == *that.p_; } |
61 | |
62 | template <typename... ARGS> |
63 | static common::IfNoLvalue<Indirection, ARGS...> Make(ARGS &&...args) { |
64 | return {new A(std::move(args)...)}; |
65 | } |
66 | |
67 | private: |
68 | A *p_{nullptr}; |
69 | }; |
70 | |
71 | // Variant with copy construction and assignment |
72 | template <typename A> class Indirection<A, true> { |
73 | public: |
74 | using element_type = A; |
75 | |
76 | Indirection() = delete; |
77 | Indirection(A *&&p) : p_{p} { |
78 | CHECK(p_ && "assigning null pointer to Indirection"); |
79 | p = nullptr; |
80 | } |
81 | Indirection(const A &x) : p_{new A(x)} {} |
82 | Indirection(A &&x) : p_{new A(std::move(x))} {} |
83 | Indirection(const Indirection &that) { |
84 | CHECK(that.p_ && "copy construction of Indirection from null Indirection"); |
85 | p_ = new A(*that.p_); |
86 | } |
87 | Indirection(Indirection &&that) : p_{that.p_} { |
88 | CHECK(p_ && "move construction of Indirection from null Indirection"); |
89 | that.p_ = nullptr; |
90 | } |
91 | ~Indirection() { |
92 | delete p_; |
93 | p_ = nullptr; |
94 | } |
95 | Indirection &operator=(const Indirection &that) { |
96 | CHECK(that.p_ && "copy assignment of Indirection from null Indirection"); |
97 | *p_ = *that.p_; |
98 | return *this; |
99 | } |
100 | Indirection &operator=(Indirection &&that) { |
101 | CHECK(that.p_ && "move assignment of null Indirection to Indirection"); |
102 | auto tmp{p_}; |
103 | p_ = that.p_; |
104 | that.p_ = tmp; |
105 | return *this; |
106 | } |
107 | |
108 | A &value() { return *p_; } |
109 | const A &value() const { return *p_; } |
110 | |
111 | bool operator==(const A &that) const { return *p_ == that; } |
112 | bool operator==(const Indirection &that) const { return *p_ == *that.p_; } |
113 | |
114 | template <typename... ARGS> |
115 | static common::IfNoLvalue<Indirection, ARGS...> Make(ARGS &&...args) { |
116 | return {new A(std::move(args)...)}; |
117 | } |
118 | |
119 | private: |
120 | A *p_{nullptr}; |
121 | }; |
122 | |
123 | template <typename A> using CopyableIndirection = Indirection<A, true>; |
124 | |
125 | // A variation of std::unique_ptr<> with a reified deletion routine. |
126 | // Used to avoid dependence cycles between shared libraries. |
127 | template <typename A> class ForwardOwningPointer { |
128 | public: |
129 | ForwardOwningPointer() {} |
130 | ForwardOwningPointer(A *p, void (*del)(A *)) : p_{p}, deleter_{del} {} |
131 | ForwardOwningPointer(ForwardOwningPointer &&that) |
132 | : p_{that.p_}, deleter_{that.deleter_} { |
133 | that.p_ = nullptr; |
134 | } |
135 | ForwardOwningPointer &operator=(ForwardOwningPointer &&that) { |
136 | p_ = that.p_; |
137 | that.p_ = nullptr; |
138 | deleter_ = that.deleter_; |
139 | return *this; |
140 | } |
141 | ~ForwardOwningPointer() { |
142 | if (p_) { |
143 | deleter_(p_); |
144 | } |
145 | } |
146 | |
147 | A &operator*() const { return *p_; } |
148 | A *operator->() const { return p_; } |
149 | operator bool() const { return p_ != nullptr; } |
150 | A *get() { return p_; } |
151 | auto get() const { return reinterpret_cast<std::add_const_t<A> *>(p_); } |
152 | A *release() { |
153 | A *result{p_}; |
154 | p_ = nullptr; |
155 | return result; |
156 | } |
157 | |
158 | void Reset(A *p = nullptr) { |
159 | if (p_) { |
160 | deleter_(p_); |
161 | } |
162 | p_ = p; |
163 | } |
164 | void Reset(A *p, void (*del)(A *)) { |
165 | Reset(p); |
166 | deleter_ = del; |
167 | } |
168 | |
169 | private: |
170 | A *p_{nullptr}; |
171 | void (*deleter_)(A *){nullptr}; |
172 | }; |
173 | } // namespace Fortran::common |
174 | #endif // FORTRAN_COMMON_INDIRECTION_H_ |
175 |
Warning: This file is not a C or C++ file. It does not have highlighting.