123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- /*
- * Copyright 2017-present Facebook, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #pragma once
- #include <folly/Poly.h>
- namespace folly {
- namespace poly {
- /**
- * A `Poly` interface for types that are equality comparable.
- */
- struct IEqualityComparable : PolyExtends<> {
- template <class T>
- static auto isEqual_(T const& _this, T const& that)
- -> decltype(std::declval<bool (&)(bool)>()(_this == that)) {
- return _this == that;
- }
- template <class T>
- using Members = FOLLY_POLY_MEMBERS(&isEqual_<T>);
- };
- /**
- * A `Poly` interface for types that are strictly orderable.
- */
- struct IStrictlyOrderable : PolyExtends<> {
- template <class T>
- static auto isLess_(T const& _this, T const& that)
- -> decltype(std::declval<bool (&)(bool)>()(_this < that)) {
- return _this < that;
- }
- template <class T>
- using Members = FOLLY_POLY_MEMBERS(&isLess_<T>);
- };
- } // namespace poly
- /// \cond
- namespace detail {
- template <class I1, class I2>
- using Comparable = Conjunction<
- std::is_same<std::decay_t<I1>, std::decay_t<I2>>,
- std::is_base_of<poly::IEqualityComparable, std::decay_t<I1>>>;
- template <class I1, class I2>
- using Orderable = Conjunction<
- std::is_same<std::decay_t<I1>, std::decay_t<I2>>,
- std::is_base_of<poly::IStrictlyOrderable, std::decay_t<I1>>>;
- } // namespace detail
- /// \endcond
- template <
- class I1,
- class I2,
- std::enable_if_t<detail::Comparable<I1, I2>::value, int> = 0>
- bool operator==(Poly<I1> const& _this, Poly<I2> const& that) {
- if (poly_empty(_this) != poly_empty(that)) {
- return false;
- } else if (poly_empty(_this)) {
- return true;
- } else if (poly_type(_this) != poly_type(that)) {
- throw BadPolyCast();
- }
- return ::folly::poly_call<0, poly::IEqualityComparable>(_this, that);
- }
- template <
- class I1,
- class I2,
- std::enable_if_t<detail::Comparable<I1, I2>::value, int> = 0>
- bool operator!=(Poly<I1> const& _this, Poly<I2> const& that) {
- return !(_this == that);
- }
- template <
- class I1,
- class I2,
- std::enable_if_t<detail::Orderable<I1, I2>::value, int> = 0>
- bool operator<(Poly<I1> const& _this, Poly<I2> const& that) {
- if (poly_empty(that)) {
- return false;
- } else if (poly_empty(_this)) {
- return true;
- } else if (poly_type(_this) != poly_type(that)) {
- throw BadPolyCast{};
- }
- return ::folly::poly_call<0, poly::IStrictlyOrderable>(_this, that);
- }
- template <
- class I1,
- class I2,
- std::enable_if_t<detail::Orderable<I1, I2>::value, int> = 0>
- bool operator>(Poly<I1> const& _this, Poly<I2> const& that) {
- return that < _this;
- }
- template <
- class I1,
- class I2,
- std::enable_if_t<detail::Orderable<I1, I2>::value, int> = 0>
- bool operator<=(Poly<I1> const& _this, Poly<I2> const& that) {
- return !(that < _this);
- }
- template <
- class I1,
- class I2,
- std::enable_if_t<detail::Orderable<I1, I2>::value, int> = 0>
- bool operator>=(Poly<I1> const& _this, Poly<I2> const& that) {
- return !(_this < that);
- }
- namespace poly {
- /**
- * A `Poly` interface for types that are move-only.
- */
- struct IMoveOnly : PolyExtends<> {
- template <class Base>
- struct Interface : Base {
- Interface() = default;
- Interface(Interface const&) = delete;
- Interface(Interface&&) = default;
- Interface& operator=(Interface const&) = delete;
- Interface& operator=(Interface&&) = default;
- using Base::Base;
- };
- };
- /**
- * A `Poly` interface for types that are copyable and movable.
- */
- struct ISemiRegular : PolyExtends<> {};
- /**
- * A `Poly` interface for types that are copyable, movable, and equality
- * comparable.
- */
- struct IRegular : PolyExtends<ISemiRegular, IEqualityComparable> {};
- } // namespace poly
- } // namespace folly
|