proxygen
PropagateConst.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 #pragma once
18 
19 #include <functional>
20 #include <type_traits>
21 #include <utility>
22 
23 #include <folly/Traits.h>
24 #include <folly/Utility.h>
25 
26 namespace folly {
27 
28 template <typename Pointer>
30 
31 template <typename Pointer>
32 constexpr Pointer& get_underlying(propagate_const<Pointer>& obj) {
33  return obj.pointer_;
34 }
35 
36 template <typename Pointer>
37 constexpr Pointer const& get_underlying(propagate_const<Pointer> const& obj) {
38  return obj.pointer_;
39 }
40 
41 namespace detail {
42 template <typename>
44 template <typename Pointer>
46 template <typename T>
48 
49 namespace propagate_const_adl {
50 using std::swap;
51 template <typename T>
53  -> decltype(swap(a, b)) {
54  swap(a, b);
55 }
56 } // namespace propagate_const_adl
57 } // namespace detail
58 
59 // mimic: std::experimental::propagate_const, C++ Library Fundamentals TS v2
60 template <typename Pointer>
61 class propagate_const {
62  public:
63  using element_type =
65 
66  constexpr propagate_const() = default;
68  propagate_const(propagate_const const&) = delete;
69 
70  template <
71  typename OtherPointer,
72  _t<std::enable_if<
75  int>> = 0>
76  constexpr explicit propagate_const(propagate_const<OtherPointer>&& other)
77  : pointer_(static_cast<OtherPointer&&>(other.pointer_)) {}
78 
79  template <
80  typename OtherPointer,
81  _t<std::enable_if<
84  int>> = 0>
86  : pointer_(static_cast<OtherPointer&&>(other.pointer_)) {}
87 
88  template <
89  typename OtherPointer,
90  _t<std::enable_if<
93  !std::is_convertible<OtherPointer&&, Pointer>::value,
94  int>> = 0>
95  constexpr explicit propagate_const(OtherPointer&& other)
96  : pointer_(static_cast<OtherPointer&&>(other)) {}
97 
98  template <
99  typename OtherPointer,
100  _t<std::enable_if<
103  std::is_convertible<OtherPointer&&, Pointer>::value,
104  int>> = 0>
105  constexpr propagate_const(OtherPointer&& other)
106  : pointer_(static_cast<OtherPointer&&>(other)) {}
107 
108  FOLLY_CPP14_CONSTEXPR propagate_const& operator=(propagate_const&&) = default;
109  propagate_const& operator=(propagate_const const&) = delete;
110 
111  template <
112  typename OtherPointer,
113  typename = _t<
117  pointer_ = static_cast<OtherPointer&&>(other.pointer_);
118  }
119 
120  template <
121  typename OtherPointer,
122  typename = _t<std::enable_if<
124  std::is_convertible<OtherPointer&&, Pointer>::value>>>
126  pointer_ = static_cast<OtherPointer&&>(other);
127  return *this;
128  }
129 
132  std::declval<Pointer&>(),
133  other.pointer_))) {
134  detail::propagate_const_adl::adl_swap(pointer_, other.pointer_);
135  }
136 
138  return get_(pointer_);
139  }
140 
141  constexpr element_type const* get() const {
142  return get_(pointer_);
143  }
144 
145  constexpr explicit operator bool() const {
146  return static_cast<bool>(pointer_);
147  }
148 
150  return *get();
151  }
152 
153  constexpr element_type const& operator*() const {
154  return *get();
155  }
156 
158  return get();
159  }
160 
161  constexpr element_type const* operator->() const {
162  return get();
163  }
164 
165  template <
166  typename OtherPointer = Pointer,
167  typename = _t<std::enable_if<
171  return get();
172  }
173 
174  template <
175  typename OtherPointer = Pointer,
176  typename = _t<std::enable_if<
179  constexpr operator element_type const*() const {
180  return get();
181  }
182 
183  private:
184  friend Pointer& get_underlying<>(propagate_const&);
185  friend Pointer const& get_underlying<>(propagate_const const&);
186  template <typename OtherPointer>
187  friend class propagate_const;
188 
189  template <typename T>
190  constexpr static T* get_(T* t) {
191  return t;
192  }
193  template <typename T>
194  constexpr static auto get_(T& t) -> decltype(t.get()) {
195  return t.get();
196  }
197 
198  Pointer pointer_;
199 };
200 
201 template <typename Pointer>
205  a.swap(b);
206 }
207 
208 template <typename Pointer>
209 constexpr bool operator==(propagate_const<Pointer> const& a, std::nullptr_t) {
210  return get_underlying(a) == nullptr;
211 }
212 
213 template <typename Pointer>
214 constexpr bool operator==(std::nullptr_t, propagate_const<Pointer> const& a) {
215  return nullptr == get_underlying(a);
216 }
217 
218 template <typename Pointer>
219 constexpr bool operator!=(propagate_const<Pointer> const& a, std::nullptr_t) {
220  return get_underlying(a) != nullptr;
221 }
222 
223 template <typename Pointer>
224 constexpr bool operator!=(std::nullptr_t, propagate_const<Pointer> const& a) {
225  return nullptr != get_underlying(a);
226 }
227 
228 template <typename Pointer>
229 constexpr bool operator==(
231  propagate_const<Pointer> const& b) {
232  return get_underlying(a) == get_underlying(b);
233 }
234 
235 template <typename Pointer>
236 constexpr bool operator!=(
238  propagate_const<Pointer> const& b) {
239  return get_underlying(a) != get_underlying(b);
240 }
241 
242 template <typename Pointer>
243 constexpr bool operator<(
245  propagate_const<Pointer> const& b) {
246  return get_underlying(a) < get_underlying(b);
247 }
248 
249 template <typename Pointer>
250 constexpr bool operator<=(
252  propagate_const<Pointer> const& b) {
253  return get_underlying(a) <= get_underlying(b);
254 }
255 
256 template <typename Pointer>
257 constexpr bool operator>(
259  propagate_const<Pointer> const& b) {
260  return get_underlying(a) > get_underlying(b);
261 }
262 
263 template <typename Pointer>
264 constexpr bool operator>=(
266  propagate_const<Pointer> const& b) {
267  return get_underlying(a) >= get_underlying(b);
268 }
269 
270 // Note: contrary to the specification, the heterogeneous comparison operators
271 // only participate in overload resolution when the equivalent heterogeneous
272 // comparison operators on the underlying pointers, as returned by invocation
273 // of get_underlying, would also participate in overload resolution.
274 
275 template <typename Pointer, typename Other>
276 constexpr auto operator==(propagate_const<Pointer> const& a, Other const& b)
277  -> decltype(get_underlying(a) == b, false) {
278  return get_underlying(a) == b;
279 }
280 
281 template <typename Pointer, typename Other>
282 constexpr auto operator!=(propagate_const<Pointer> const& a, Other const& b)
283  -> decltype(get_underlying(a) != b, false) {
284  return get_underlying(a) != b;
285 }
286 
287 template <typename Pointer, typename Other>
288 constexpr auto operator<(propagate_const<Pointer> const& a, Other const& b)
289  -> decltype(get_underlying(a) < b, false) {
290  return get_underlying(a) < b;
291 }
292 
293 template <typename Pointer, typename Other>
294 constexpr auto operator<=(propagate_const<Pointer> const& a, Other const& b)
295  -> decltype(get_underlying(a) <= b, false) {
296  return get_underlying(a) <= b;
297 }
298 
299 template <typename Pointer, typename Other>
300 constexpr auto operator>(propagate_const<Pointer> const& a, Other const& b)
301  -> decltype(get_underlying(a) > b, false) {
302  return get_underlying(a) > b;
303 }
304 
305 template <typename Pointer, typename Other>
306 constexpr auto operator>=(propagate_const<Pointer> const& a, Other const& b)
307  -> decltype(get_underlying(a) >= b, false) {
308  return get_underlying(a) >= b;
309 }
310 
311 template <typename Other, typename Pointer>
312 constexpr auto operator==(Other const& a, propagate_const<Pointer> const& b)
313  -> decltype(a == get_underlying(b), false) {
314  return a == get_underlying(b);
315 }
316 
317 template <typename Other, typename Pointer>
318 constexpr auto operator!=(Other const& a, propagate_const<Pointer> const& b)
319  -> decltype(a != get_underlying(b), false) {
320  return a != get_underlying(b);
321 }
322 
323 template <typename Other, typename Pointer>
324 constexpr auto operator<(Other const& a, propagate_const<Pointer> const& b)
325  -> decltype(a < get_underlying(b), false) {
326  return a < get_underlying(b);
327 }
328 
329 template <typename Other, typename Pointer>
330 constexpr auto operator<=(Other const& a, propagate_const<Pointer> const& b)
331  -> decltype(a <= get_underlying(b), false) {
332  return a <= get_underlying(b);
333 }
334 
335 template <typename Other, typename Pointer>
336 constexpr auto operator>(Other const& a, propagate_const<Pointer> const& b)
337  -> decltype(a > get_underlying(b), false) {
338  return a > get_underlying(b);
339 }
340 
341 template <typename Other, typename Pointer>
342 constexpr auto operator>=(Other const& a, propagate_const<Pointer> const& b)
343  -> decltype(a >= get_underlying(b), false) {
344  return a >= get_underlying(b);
345 }
346 
347 } // namespace folly
348 
349 namespace std {
350 
351 template <typename Pointer>
352 struct hash<folly::propagate_const<Pointer>> : private hash<Pointer> {
353  using hash<Pointer>::hash;
354 
355  size_t operator()(folly::propagate_const<Pointer> const& obj) const {
356  return hash<Pointer>::operator()(folly::get_underlying(obj));
357  }
358 };
359 
360 template <typename Pointer>
361 struct equal_to<folly::propagate_const<Pointer>> : private equal_to<Pointer> {
362  using equal_to<Pointer>::equal_to;
363 
364  constexpr bool operator()(
367  return equal_to<Pointer>::operator()(
369  }
370 };
371 
372 template <typename Pointer>
373 struct not_equal_to<folly::propagate_const<Pointer>>
374  : private not_equal_to<Pointer> {
375  using not_equal_to<Pointer>::not_equal_to;
376 
377  constexpr bool operator()(
380  return not_equal_to<Pointer>::operator()(
382  }
383 };
384 
385 template <typename Pointer>
386 struct less<folly::propagate_const<Pointer>> : private less<Pointer> {
387  using less<Pointer>::less;
388 
389  constexpr bool operator()(
392  return less<Pointer>::operator()(
394  }
395 };
396 
397 template <typename Pointer>
398 struct greater<folly::propagate_const<Pointer>> : private greater<Pointer> {
399  using greater<Pointer>::greater;
400 
401  constexpr bool operator()(
404  return greater<Pointer>::operator()(
406  }
407 };
408 
409 template <typename Pointer>
410 struct less_equal<folly::propagate_const<Pointer>>
411  : private less_equal<Pointer> {
412  using less_equal<Pointer>::less_equal;
413 
414  constexpr bool operator()(
417  return less_equal<Pointer>::operator()(
419  }
420 };
421 
422 template <typename Pointer>
423 struct greater_equal<folly::propagate_const<Pointer>>
424  : private greater_equal<Pointer> {
425  using greater_equal<Pointer>::greater_equal;
426 
427  constexpr bool operator()(
430  return greater_equal<Pointer>::operator()(
432  }
433 };
434 
435 } // namespace std
bool operator>(const Expected< Value, Error > &lhs, const Expected< Value, Error > &rhs)
Definition: Expected.h:1349
constexpr propagate_const(OtherPointer &&other)
constexpr element_type const & operator*() const
char b
constexpr bool operator()(folly::propagate_const< Pointer > const &a, folly::propagate_const< Pointer > const &b)
_t< std::remove_reference< decltype(*std::declval< Pointer & >())>> element_type
#define FOLLY_CPP14_CONSTEXPR
Definition: Portability.h:424
constexpr bool operator()(folly::propagate_const< Pointer > const &a, folly::propagate_const< Pointer > const &b)
STL namespace.
static constexpr auto get_(T &t) -> decltype(t.get())
constexpr bool operator()(folly::propagate_const< Pointer > const &a, folly::propagate_const< Pointer > const &b)
constexpr bool operator()(folly::propagate_const< Pointer > const &a, folly::propagate_const< Pointer > const &b)
folly::std T
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
constexpr element_type const * operator->() const
requires E e noexcept(noexcept(s.error(std::move(e))))
FOLLY_CPP14_CONSTEXPR element_type & operator*()
static constexpr T * get_(T *t)
constexpr propagate_const(propagate_const< OtherPointer > &&other)
bool_constant< true > true_type
Definition: gtest-port.h:2210
bool operator!=(const Unexpected< Error > &lhs, const Unexpected< Error > &rhs)
Definition: Expected.h:766
FOLLY_CPP14_CONSTEXPR void swap(propagate_const &other) noexcept(noexcept(detail::propagate_const_adl::adl_swap(std::declval< Pointer & >(), other.pointer_)))
typename T::type _t
Definition: Traits.h:171
size_t operator()(folly::propagate_const< Pointer > const &obj) const
char a
FOLLY_CPP14_CONSTEXPR void swap(propagate_const< Pointer > &a, propagate_const< Pointer > &b) noexcept(noexcept(a.swap(b)))
FOLLY_CPP14_CONSTEXPR element_type * operator->()
static const char *const value
Definition: Conv.cpp:50
constexpr bool operator()(folly::propagate_const< Pointer > const &a, folly::propagate_const< Pointer > const &b)
FOLLY_CPP14_CONSTEXPR propagate_const & operator=(propagate_const< OtherPointer > &&other)
bool operator>=(const Expected< Value, Error > &lhs, const Expected< Value, Error > &rhs)
Definition: Expected.h:1358
void swap(exception_wrapper &a, exception_wrapper &b) noexcept
auto adl_swap(T &a, T &b) noexcept(noexcept(swap(a, b))) -> decltype(swap(a, b))
bool operator==(const Unexpected< Error > &lhs, const Unexpected< Error > &rhs)
Definition: Expected.h:758
constexpr Pointer & get_underlying(propagate_const< Pointer > &obj)
bool operator<=(const Expected< Value, Error > &lhs, const Expected< Value, Error > &rhs)
Definition: Expected.h:1340
bool_constant< false > false_type
Definition: gtest-port.h:2209
constexpr bool operator()(folly::propagate_const< Pointer > const &a, folly::propagate_const< Pointer > const &b)
FOLLY_CPP14_CONSTEXPR propagate_const & operator=(OtherPointer &&other)
std::enable_if< IsLessThanComparable< Value >::value, bool >::type operator<(const Expected< Value, Error > &lhs, const Expected< Value, Error > &rhs)
Definition: Expected.h:1321