proxygen
Poly-inl.h
Go to the documentation of this file.
1 /*
2  * Copyright 2017-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 namespace folly {
18 namespace detail {
19 
20 template <class I>
21 inline PolyVal<I>::PolyVal(PolyVal&& that) noexcept {
22  that.vptr_->ops_(Op::eMove, &that, static_cast<Data*>(this));
23  vptr_ = std::exchange(that.vptr_, vtable<I>());
24 }
25 
26 template <class I>
27 inline PolyVal<I>::PolyVal(PolyOrNonesuch const& that) {
28  that.vptr_->ops_(
29  Op::eCopy, const_cast<Data*>(that._data_()), PolyAccess::data(*this));
30  vptr_ = that.vptr_;
31 }
32 
33 template <class I>
34 inline PolyVal<I>::~PolyVal() {
35  vptr_->ops_(Op::eNuke, this, nullptr);
36 }
37 
38 template <class I>
39 inline Poly<I>& PolyVal<I>::operator=(PolyVal that) noexcept {
40  vptr_->ops_(Op::eNuke, _data_(), nullptr);
41  that.vptr_->ops_(Op::eMove, that._data_(), _data_());
42  vptr_ = std::exchange(that.vptr_, vtable<I>());
43  return static_cast<Poly<I>&>(*this);
44 }
45 
46 template <class I>
48 inline PolyVal<I>::PolyVal(T&& t) {
49  using U = std::decay_t<T>;
50  static_assert(
52  "This Poly<> requires copyability, and the source object is not "
53  "copyable");
54  // The static and dynamic types should match; otherwise, this will slice.
55  assert(typeid(t) == typeid(_t<std::decay<T>>) ||
56  !"Dynamic and static exception types don't match. Object would "
57  "be sliced when storing in Poly.");
58  if (inSitu<U>()) {
59  ::new (static_cast<void*>(&_data_()->buff_)) U(static_cast<T&&>(t));
60  } else {
61  _data_()->pobj_ = new U(static_cast<T&&>(t));
62  }
63  vptr_ = vtableFor<I, U>();
64 }
65 
66 template <class I>
68 inline PolyVal<I>::PolyVal(Poly<I2> that) {
69  static_assert(
70  !Copyable::value || std::is_copy_constructible<Poly<I2>>::value,
71  "This Poly<> requires copyability, and the source object is not "
72  "copyable");
73  auto* that_vptr = PolyAccess::vtable(that);
74  if (that_vptr->state_ != State::eEmpty) {
75  that_vptr->ops_(Op::eMove, PolyAccess::data(that), _data_());
76  vptr_ = &select<I>(*std::exchange(that_vptr, vtable<std::decay_t<I2>>()));
77  }
78 }
79 
80 template <class I>
82 inline Poly<I>& PolyVal<I>::operator=(T&& t) {
83  *this = PolyVal(static_cast<T&&>(t));
84  return static_cast<Poly<I>&>(*this);
85 }
86 
87 template <class I>
88 template <class I2, std::enable_if_t<ValueCompatible<I, I2>::value, int>>
89 inline Poly<I>& PolyVal<I>::operator=(Poly<I2> that) {
90  *this = PolyVal(std::move(that));
91  return static_cast<Poly<I>&>(*this);
92 }
93 
94 template <class I>
95 inline void PolyVal<I>::swap(Poly<I>& that) noexcept {
96  switch (vptr_->state_) {
97  case State::eEmpty:
98  *this = std::move(that);
99  break;
100  case State::eOnHeap:
101  if (State::eOnHeap == that.vptr_->state_) {
102  std::swap(_data_()->pobj_, that._data_()->pobj_);
103  std::swap(vptr_, that.vptr_);
104  return;
105  }
107  case State::eInSitu:
108  std::swap(
109  *this, static_cast<PolyVal<I>&>(that)); // NOTE: qualified, not ADL
110  }
111 }
112 
113 template <class I>
114 inline AddCvrefOf<PolyRoot<I>, I>& PolyRef<I>::_polyRoot_() const noexcept {
115  return const_cast<AddCvrefOf<PolyRoot<I>, I>&>(
116  static_cast<PolyRoot<I> const&>(*this));
117 }
118 
119 template <class I>
120 constexpr RefType PolyRef<I>::refType() noexcept {
121  using J = std::remove_reference_t<I>;
123  ? RefType::eRvalue
124  : std::is_const<J>::value ? RefType::eConstLvalue : RefType::eLvalue;
125 }
126 
127 template <class I>
128 template <class That, class I2>
129 inline PolyRef<I>::PolyRef(That&& that, Type<I2>) {
130  auto* that_vptr = PolyAccess::vtable(PolyAccess::root(that));
131  detail::State const that_state = that_vptr->state_;
132  if (that_state == State::eEmpty) {
133  throw BadPolyAccess();
134  }
135  auto* that_data = PolyAccess::data(PolyAccess::root(that));
136  _data_()->pobj_ = that_state == State::eInSitu
137  ? const_cast<void*>(static_cast<void const*>(&that_data->buff_))
138  : that_data->pobj_;
139  this->vptr_ = &select<std::decay_t<I>>(
140  *static_cast<VTable<std::decay_t<I2>> const*>(that_vptr->ops_(
141  Op::eRefr, nullptr, reinterpret_cast<void*>(refType()))));
142 }
143 
144 template <class I>
145 inline PolyRef<I>::PolyRef(PolyRef const& that) noexcept {
146  _data_()->pobj_ = that._data_()->pobj_;
147  this->vptr_ = that.vptr_;
148 }
149 
150 template <class I>
151 inline Poly<I>& PolyRef<I>::operator=(PolyRef const& that) noexcept {
152  _data_()->pobj_ = that._data_()->pobj_;
153  this->vptr_ = that.vptr_;
154  return static_cast<Poly<I>&>(*this);
155 }
156 
157 template <class I>
158 template <class T, std::enable_if_t<ModelsInterface<T, I>::value, int>>
159 inline PolyRef<I>::PolyRef(T&& t) noexcept {
160  _data_()->pobj_ =
161  const_cast<void*>(static_cast<void const*>(std::addressof(t)));
162  this->vptr_ = vtableFor<std::decay_t<I>, AddCvrefOf<std::decay_t<T>, I>>();
163 }
164 
165 template <class I>
166 template <
167  class I2,
169 inline PolyRef<I>::PolyRef(Poly<I2>&& that) noexcept(
170  std::is_reference<I2>::value)
171  : PolyRef{that, Type<I2>{}} {
172  static_assert(
173  Disjunction<std::is_reference<I2>, std::is_rvalue_reference<I>>::value,
174  "Attempting to construct a Poly that is a reference to a temporary. "
175  "This is probably a mistake.");
176 }
177 
178 template <class I>
179 template <class T, std::enable_if_t<ModelsInterface<T, I>::value, int>>
180 inline Poly<I>& PolyRef<I>::operator=(T&& t) noexcept {
181  *this = PolyRef(static_cast<T&&>(t));
182  return static_cast<Poly<I>&>(*this);
183 }
184 
185 template <class I>
186 template <
187  class I2,
188  std::enable_if_t<ReferenceCompatible<I, I2, I2&&>::value, int>>
189 inline Poly<I>& PolyRef<I>::operator=(Poly<I2>&& that) noexcept(
190  std::is_reference<I2>::value) {
191  *this = PolyRef(std::move(that));
192  return static_cast<Poly<I>&>(*this);
193 }
194 
195 template <class I>
196 template <
197  class I2,
199 inline Poly<I>& PolyRef<I>::operator=(Poly<I2>& that) noexcept(
201  *this = PolyRef(that);
202  return static_cast<Poly<I>&>(*this);
203 }
204 
205 template <class I>
206 template <
207  class I2,
209 inline Poly<I>& PolyRef<I>::operator=(Poly<I2> const& that) noexcept(
211  *this = PolyRef(that);
212  return static_cast<Poly<I>&>(*this);
213 }
214 
215 template <class I>
216 inline void PolyRef<I>::swap(Poly<I>& that) noexcept {
217  std::swap(_data_()->pobj_, that._data_()->pobj_);
218  std::swap(this->vptr_, that.vptr_);
219 }
220 
221 template <class I>
222 inline AddCvrefOf<PolyImpl<I>, I>& PolyRef<I>::get() const noexcept {
223  return const_cast<AddCvrefOf<PolyImpl<I>, I>&>(
224  static_cast<PolyImpl<I> const&>(*this));
225 }
226 
227 } // namespace detail
228 } // namespace folly
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
STL namespace.
folly::std T
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
requires E e noexcept(noexcept(s.error(std::move(e))))
State
See Core for details.
Definition: Core.h:43
typename T::type _t
Definition: Traits.h:171
static const char *const value
Definition: Conv.cpp:50
T exchange(T &obj, U &&new_value)
Definition: Utility.h:120
const
Definition: upload.py:398
uint64_t value(const typename LockFreeRingBuffer< T, Atom >::Cursor &rbcursor)
void swap(SwapTrackingAlloc< T > &, SwapTrackingAlloc< T > &)
Definition: F14TestUtil.h:414
PUSHMI_INLINE_VAR constexpr detail::get_fn< T > get
Definition: submit.h:391
static constexpr uint64_t data[1]
Definition: Fingerprint.cpp:43
#define FOLLY_FALLTHROUGH
Definition: CppAttributes.h:63