proxygen
Poly.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 // TODO: [x] "cast" from Poly<C&> to Poly<C&&>
18 // TODO: [ ] copy/move from Poly<C&>/Poly<C&&> to Poly<C>
19 // TODO: [ ] copy-on-write?
20 // TODO: [ ] down- and cross-casting? (Possible?)
21 // TODO: [ ] shared ownership? (Dubious.)
22 // TODO: [ ] can games be played with making the VTable a member of a struct
23 // with strange alignment such that the address of the VTable can
24 // be used to tell whether the object is stored in-situ or not?
25 
26 #pragma once
27 
28 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 5
29 #error Folly.Poly requires gcc-5 or greater
30 #endif
31 
32 #include <cassert>
33 #include <new>
34 #include <type_traits>
35 #include <typeinfo>
36 #include <utility>
37 
38 #include <folly/CPortability.h>
39 #include <folly/CppAttributes.h>
40 #include <folly/Traits.h>
41 #include <folly/detail/TypeList.h>
42 #include <folly/lang/Assume.h>
43 
44 #if !defined(__cpp_inline_variables)
45 #define FOLLY_INLINE_CONSTEXPR constexpr
46 #else
47 #define FOLLY_INLINE_CONSTEXPR inline constexpr
48 #endif
49 
50 #include <folly/PolyException.h>
52 
53 namespace folly {
54 template <class I>
55 struct Poly;
56 
104 template <
105  class Node,
106  class Tfx = detail::MetaIdentity,
107  class Access = detail::PolyAccess>
108 using PolySelf = decltype(Access::template self_<Node, Tfx>());
109 
117 
118 #if !defined(__cpp_template_auto)
119 
136 #define FOLLY_POLY_MEMBERS(...) \
137  typename decltype(::folly::detail::deduceMembers( \
138  __VA_ARGS__))::template Members<__VA_ARGS__>
139 
158 #define FOLLY_POLY_MEMBER(SIG, MEM) \
159  ::folly::detail::MemberDef< \
160  ::folly::detail::Member<decltype(::folly::sig<SIG>(MEM)), MEM>>::value
161 
165 template <class... Ts>
166 using PolyMembers = detail::TypeList<Ts...>;
167 
168 #else
169 #define FOLLY_POLY_MEMBER(SIG, MEM) ::folly::sig<SIG>(MEM)
170 #define FOLLY_POLY_MEMBERS(...) ::folly::PolyMembers<__VA_ARGS__>
171 
172 template <auto... Ps>
173 struct PolyMembers {};
174 
175 #endif
176 
196 template <class... I>
197 struct PolyExtends : virtual I... {
199 
200  template <class Base>
201  struct Interface : Base {
202  Interface() = default;
203  using Base::Base;
204  };
205 
206  template <class...>
208 };
209 
211 
235 template <std::size_t N, typename This, typename... As>
236 auto poly_call(This&& _this, As&&... as)
237  -> decltype(detail::PolyAccess::call<N>(
238  static_cast<This&&>(_this),
239  static_cast<As&&>(as)...)) {
240  return detail::PolyAccess::call<N>(
241  static_cast<This&&>(_this), static_cast<As&&>(as)...);
242 }
243 
245 template <std::size_t N, class I, class Tail, typename... As>
246 decltype(auto) poly_call(detail::PolyNode<I, Tail>&& _this, As&&... as) {
247  using This = detail::InterfaceOf<I, detail::PolyNode<I, Tail>>;
248  return detail::PolyAccess::call<N>(
249  static_cast<This&&>(_this), static_cast<As&&>(as)...);
250 }
251 
253 template <std::size_t N, class I, class Tail, typename... As>
254 decltype(auto) poly_call(detail::PolyNode<I, Tail>& _this, As&&... as) {
255  using This = detail::InterfaceOf<I, detail::PolyNode<I, Tail>>;
256  return detail::PolyAccess::call<N>(
257  static_cast<This&>(_this), static_cast<As&&>(as)...);
258 }
259 
261 template <std::size_t N, class I, class Tail, typename... As>
262 decltype(auto) poly_call(detail::PolyNode<I, Tail> const& _this, As&&... as) {
263  using This = detail::InterfaceOf<I, detail::PolyNode<I, Tail>>;
264  return detail::PolyAccess::call<N>(
265  static_cast<This const&>(_this), static_cast<As&&>(as)...);
266 }
267 
269 template <
270  std::size_t N,
271  class I,
272  class Poly,
273  typename... As,
275 auto poly_call(Poly&& _this, As&&... as) -> decltype(poly_call<N, I>(
276  static_cast<Poly&&>(_this).get(),
277  static_cast<As&&>(as)...)) {
278  return poly_call<N, I>(
279  static_cast<Poly&&>(_this).get(), static_cast<As&&>(as)...);
280 }
281 
284 template <std::size_t N, class I, typename... As>
285 [[noreturn]] detail::Bottom poly_call(detail::ArchetypeBase const&, As&&...) {
287 }
289 
291 
303 template <class T, class I>
304 detail::AddCvrefOf<T, I>&& poly_cast(detail::PolyRoot<I>&& that) {
305  return detail::PolyAccess::cast<T>(std::move(that));
306 }
307 
309 template <class T, class I>
310 detail::AddCvrefOf<T, I>& poly_cast(detail::PolyRoot<I>& that) {
311  return detail::PolyAccess::cast<T>(that);
312 }
313 
315 template <class T, class I>
316 detail::AddCvrefOf<T, I> const& poly_cast(detail::PolyRoot<I> const& that) {
317  return detail::PolyAccess::cast<T>(that);
318 }
319 
322 template <class T, class I>
323 [[noreturn]] detail::AddCvrefOf<T, I>&& poly_cast(detail::ArchetypeRoot<I>&&) {
325 }
326 
328 template <class T, class I>
329 [[noreturn]] detail::AddCvrefOf<T, I>& poly_cast(detail::ArchetypeRoot<I>&) {
331 }
332 
334 template <class T, class I>
335 [[noreturn]] detail::AddCvrefOf<T, I> const& poly_cast(
336  detail::ArchetypeRoot<I> const&) {
338 }
340 
342 template <
343  class T,
344  class Poly,
345  std::enable_if_t<detail::IsPoly<Poly>::value, int> = 0>
346 constexpr auto poly_cast(Poly&& that)
347  -> decltype(poly_cast<T>(std::declval<Poly>().get())) {
348  return poly_cast<T>(static_cast<Poly&&>(that).get());
349 }
350 
352 
357 template <class I>
358 std::type_info const& poly_type(detail::PolyRoot<I> const& that) noexcept {
359  return detail::PolyAccess::type(that);
360 }
361 
364 [[noreturn]] inline std::type_info const& poly_type(
365  detail::ArchetypeBase const&) noexcept {
367 }
369 
372 constexpr auto poly_type(Poly const& that) noexcept
373  -> decltype(poly_type(that.get())) {
374  return poly_type(that.get());
375 }
376 
378 
382 template <class I>
383 bool poly_empty(detail::PolyRoot<I> const& that) noexcept {
384  return detail::State::eEmpty == detail::PolyAccess::vtable(that)->state_;
385 }
386 
388 template <class I>
389 constexpr bool poly_empty(detail::PolyRoot<I&&> const&) noexcept {
390  return false;
391 }
392 
394 template <class I>
395 constexpr bool poly_empty(detail::PolyRoot<I&> const&) noexcept {
396  return false;
397 }
398 
400 template <class I>
401 constexpr bool poly_empty(Poly<I&&> const&) noexcept {
402  return false;
403 }
404 
406 template <class I>
407 constexpr bool poly_empty(Poly<I&> const&) noexcept {
408  return false;
409 }
410 
412 [[noreturn]] inline bool poly_empty(detail::ArchetypeBase const&) noexcept {
414 }
416 
418 
423 template <
424  class I,
425  std::enable_if_t<detail::Not<std::is_reference<I>>::value, int> = 0>
426 constexpr Poly<I>&& poly_move(detail::PolyRoot<I>& that) noexcept {
427  return static_cast<Poly<I>&&>(static_cast<Poly<I>&>(that));
428 }
429 
431 template <
432  class I,
433  std::enable_if_t<detail::Not<std::is_const<I>>::value, int> = 0>
434 Poly<I&&> poly_move(detail::PolyRoot<I&> const& that) noexcept {
435  return detail::PolyAccess::move(that);
436 }
437 
439 template <class I>
440 Poly<I const&> poly_move(detail::PolyRoot<I const&> const& that) noexcept {
441  return detail::PolyAccess::move(that);
442 }
443 
446 [[noreturn]] inline detail::ArchetypeBase poly_move(
447  detail::ArchetypeBase const&) noexcept {
449 }
451 
454 constexpr auto poly_move(Poly& that) noexcept
455  -> decltype(poly_move(that.get())) {
456  return poly_move(that.get());
457 }
458 
460 namespace detail {
465 template <class I>
466 struct PolyVal : PolyImpl<I> {
467  private:
468  friend PolyAccess;
469 
470  struct NoneSuch {};
471  using Copyable = std::is_copy_constructible<PolyImpl<I>>;
472  using PolyOrNonesuch = If<Copyable::value, PolyVal, NoneSuch>;
473 
474  using PolyRoot<I>::vptr_;
475 
476  PolyRoot<I>& _polyRoot_() noexcept {
477  return *this;
478  }
479  PolyRoot<I> const& _polyRoot_() const noexcept {
480  return *this;
481  }
482 
483  Data* _data_() noexcept {
484  return PolyAccess::data(*this);
485  }
486  Data const* _data_() const noexcept {
487  return PolyAccess::data(*this);
488  }
489 
490  public:
495  PolyVal() = default;
500  PolyVal(PolyVal&& that) noexcept;
505  /* implicit */ PolyVal(PolyOrNonesuch const& that);
506 
507  ~PolyVal();
508 
512  using PolyImpl<I>::PolyImpl;
513 
518  Poly<I>& operator=(PolyVal that) noexcept;
519 
524  /* implicit */ PolyVal(T&& t);
525 
531  /* implicit */ PolyVal(Poly<I2> that);
532 
538  Poly<I>& operator=(T&& t);
539 
545  Poly<I>& operator=(Poly<I2> that);
546 
550  void swap(Poly<I>& that) noexcept;
551 };
552 
554 
558 template <class I>
559 struct PolyRef : private PolyImpl<I> {
560  private:
561  friend PolyAccess;
562 
563  AddCvrefOf<PolyRoot<I>, I>& _polyRoot_() const noexcept;
564 
565  Data* _data_() noexcept {
566  return PolyAccess::data(*this);
567  }
568  Data const* _data_() const noexcept {
569  return PolyAccess::data(*this);
570  }
571 
572  static constexpr RefType refType() noexcept;
573 
574  protected:
575  template <class That, class I2>
576  PolyRef(That&& that, Type<I2>);
577 
578  public:
584  PolyRef(PolyRef const& that) noexcept;
585 
591  Poly<I>& operator=(PolyRef const& that) noexcept;
592 
598  /* implicit */ PolyRef(T&& t) noexcept;
599 
603  template <
604  class I2,
606  /* implicit */ PolyRef(Poly<I2>&& that) noexcept(
608 
609  template <
610  class I2,
612  /* implicit */ PolyRef(Poly<I2>& that) noexcept(std::is_reference<I2>::value)
613  : PolyRef{that, Type<I2>{}} {}
614 
615  template <
616  class I2,
618  /* implicit */ PolyRef(Poly<I2> const& that) noexcept(
620  : PolyRef{that, Type<I2>{}} {}
621 
627  Poly<I>& operator=(T&& t) noexcept;
628 
632  template <
633  class I2,
634  std::enable_if_t<ReferenceCompatible<I, I2, I2&&>::value, int> = 0>
636 
640  template <
641  class I2,
642  std::enable_if_t<ReferenceCompatible<I, I2, I2&>::value, int> = 0>
644 
648  template <
649  class I2,
650  std::enable_if_t<ReferenceCompatible<I, I2, I2 const&>::value, int> = 0>
651  Poly<I>& operator=(Poly<I2> const& that) noexcept(
653 
657  void swap(Poly<I>& that) noexcept;
658 
662  AddCvrefOf<PolyImpl<I>, I>& get() const noexcept;
663 
667  AddCvrefOf<PolyImpl<I>, I>& operator*() const noexcept {
668  return get();
669  }
670 
674  auto operator-> () const noexcept {
675  return &get();
676  }
677 };
678 
679 template <class I>
680 using PolyValOrRef = If<std::is_reference<I>::value, PolyRef<I>, PolyVal<I>>;
681 } // namespace detail
683 
1127 template <class I>
1128 struct Poly final : detail::PolyValOrRef<I> {
1129  friend detail::PolyAccess;
1130  Poly() = default;
1131  using detail::PolyValOrRef<I>::PolyValOrRef;
1132  using detail::PolyValOrRef<I>::operator=;
1133 };
1134 
1138 template <class I>
1139 void swap(Poly<I>& left, Poly<I>& right) noexcept {
1140  left.swap(right);
1141 }
1142 
1164 template <class Sig>
1165 FOLLY_INLINE_CONSTEXPR detail::Sig<Sig> const sig = {};
1166 
1167 } // namespace folly
1168 
1169 #include <folly/Poly-inl.h>
1170 
1171 #undef FOLLY_INLINE_CONSTEXPR
std::type_info const & poly_type(detail::PolyRoot< I > const &that) noexcept
Definition: Poly.h:358
PskType type
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
folly::std T
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
requires E e noexcept(noexcept(s.error(std::move(e))))
#define FOLLY_INLINE_CONSTEXPR
Definition: Poly.h:45
MetaApply< impl::If_< If_ >, Then, Else > If
Definition: TypeList.h:159
FOLLY_ALWAYS_INLINE void assume_unreachable()
Definition: Assume.h:59
auto poly_call(This &&_this, As &&...as) -> decltype(detail::PolyAccess::call< N >(static_cast< This && >(_this), static_cast< As && >(as)...))
Definition: Poly.h:236
detail::TypeList< Ts... > PolyMembers
Definition: PolyDetail.h:71
constexpr detail::Sig< Sig > const sig
Definition: Poly.h:1165
AtomicCounter< T, DeterministicAtomic > Base
bool poly_empty(detail::PolyRoot< I > const &that) noexcept
Definition: Poly.h:383
static const char *const value
Definition: Conv.cpp:50
detail::AddCvrefOf< T, I > & poly_cast(detail::PolyRoot< I > &)
Definition: Poly.h:310
void swap(exception_wrapper &a, exception_wrapper &b) noexcept
constexpr Poly< I > && poly_move(detail::PolyRoot< I > &that) noexcept
Definition: Poly.h:426
const
Definition: upload.py:398
uint64_t value(const typename LockFreeRingBuffer< T, Atom >::Cursor &rbcursor)
Collect as()
Definition: Base.h:811
static constexpr uint64_t data[1]
Definition: Fingerprint.cpp:43
decltype(Access::template self_< Node, Tfx >()) PolySelf
Definition: Poly.h:108