Regular.h 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  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. #pragma once
  17. #include <folly/Poly.h>
  18. namespace folly {
  19. namespace poly {
  20. /**
  21. * A `Poly` interface for types that are equality comparable.
  22. */
  23. struct IEqualityComparable : PolyExtends<> {
  24. template <class T>
  25. static auto isEqual_(T const& _this, T const& that)
  26. -> decltype(std::declval<bool (&)(bool)>()(_this == that)) {
  27. return _this == that;
  28. }
  29. template <class T>
  30. using Members = FOLLY_POLY_MEMBERS(&isEqual_<T>);
  31. };
  32. /**
  33. * A `Poly` interface for types that are strictly orderable.
  34. */
  35. struct IStrictlyOrderable : PolyExtends<> {
  36. template <class T>
  37. static auto isLess_(T const& _this, T const& that)
  38. -> decltype(std::declval<bool (&)(bool)>()(_this < that)) {
  39. return _this < that;
  40. }
  41. template <class T>
  42. using Members = FOLLY_POLY_MEMBERS(&isLess_<T>);
  43. };
  44. } // namespace poly
  45. /// \cond
  46. namespace detail {
  47. template <class I1, class I2>
  48. using Comparable = Conjunction<
  49. std::is_same<std::decay_t<I1>, std::decay_t<I2>>,
  50. std::is_base_of<poly::IEqualityComparable, std::decay_t<I1>>>;
  51. template <class I1, class I2>
  52. using Orderable = Conjunction<
  53. std::is_same<std::decay_t<I1>, std::decay_t<I2>>,
  54. std::is_base_of<poly::IStrictlyOrderable, std::decay_t<I1>>>;
  55. } // namespace detail
  56. /// \endcond
  57. template <
  58. class I1,
  59. class I2,
  60. std::enable_if_t<detail::Comparable<I1, I2>::value, int> = 0>
  61. bool operator==(Poly<I1> const& _this, Poly<I2> const& that) {
  62. if (poly_empty(_this) != poly_empty(that)) {
  63. return false;
  64. } else if (poly_empty(_this)) {
  65. return true;
  66. } else if (poly_type(_this) != poly_type(that)) {
  67. throw BadPolyCast();
  68. }
  69. return ::folly::poly_call<0, poly::IEqualityComparable>(_this, that);
  70. }
  71. template <
  72. class I1,
  73. class I2,
  74. std::enable_if_t<detail::Comparable<I1, I2>::value, int> = 0>
  75. bool operator!=(Poly<I1> const& _this, Poly<I2> const& that) {
  76. return !(_this == that);
  77. }
  78. template <
  79. class I1,
  80. class I2,
  81. std::enable_if_t<detail::Orderable<I1, I2>::value, int> = 0>
  82. bool operator<(Poly<I1> const& _this, Poly<I2> const& that) {
  83. if (poly_empty(that)) {
  84. return false;
  85. } else if (poly_empty(_this)) {
  86. return true;
  87. } else if (poly_type(_this) != poly_type(that)) {
  88. throw BadPolyCast{};
  89. }
  90. return ::folly::poly_call<0, poly::IStrictlyOrderable>(_this, that);
  91. }
  92. template <
  93. class I1,
  94. class I2,
  95. std::enable_if_t<detail::Orderable<I1, I2>::value, int> = 0>
  96. bool operator>(Poly<I1> const& _this, Poly<I2> const& that) {
  97. return that < _this;
  98. }
  99. template <
  100. class I1,
  101. class I2,
  102. std::enable_if_t<detail::Orderable<I1, I2>::value, int> = 0>
  103. bool operator<=(Poly<I1> const& _this, Poly<I2> const& that) {
  104. return !(that < _this);
  105. }
  106. template <
  107. class I1,
  108. class I2,
  109. std::enable_if_t<detail::Orderable<I1, I2>::value, int> = 0>
  110. bool operator>=(Poly<I1> const& _this, Poly<I2> const& that) {
  111. return !(_this < that);
  112. }
  113. namespace poly {
  114. /**
  115. * A `Poly` interface for types that are move-only.
  116. */
  117. struct IMoveOnly : PolyExtends<> {
  118. template <class Base>
  119. struct Interface : Base {
  120. Interface() = default;
  121. Interface(Interface const&) = delete;
  122. Interface(Interface&&) = default;
  123. Interface& operator=(Interface const&) = delete;
  124. Interface& operator=(Interface&&) = default;
  125. using Base::Base;
  126. };
  127. };
  128. /**
  129. * A `Poly` interface for types that are copyable and movable.
  130. */
  131. struct ISemiRegular : PolyExtends<> {};
  132. /**
  133. * A `Poly` interface for types that are copyable, movable, and equality
  134. * comparable.
  135. */
  136. struct IRegular : PolyExtends<ISemiRegular, IEqualityComparable> {};
  137. } // namespace poly
  138. } // namespace folly