/* * 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 namespace folly { namespace poly { /** * A `Poly` interface for types that are equality comparable. */ struct IEqualityComparable : PolyExtends<> { template static auto isEqual_(T const& _this, T const& that) -> decltype(std::declval()(_this == that)) { return _this == that; } template using Members = FOLLY_POLY_MEMBERS(&isEqual_); }; /** * A `Poly` interface for types that are strictly orderable. */ struct IStrictlyOrderable : PolyExtends<> { template static auto isLess_(T const& _this, T const& that) -> decltype(std::declval()(_this < that)) { return _this < that; } template using Members = FOLLY_POLY_MEMBERS(&isLess_); }; } // namespace poly /// \cond namespace detail { template using Comparable = Conjunction< std::is_same, std::decay_t>, std::is_base_of>>; template using Orderable = Conjunction< std::is_same, std::decay_t>, std::is_base_of>>; } // namespace detail /// \endcond template < class I1, class I2, std::enable_if_t::value, int> = 0> bool operator==(Poly const& _this, Poly 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::value, int> = 0> bool operator!=(Poly const& _this, Poly const& that) { return !(_this == that); } template < class I1, class I2, std::enable_if_t::value, int> = 0> bool operator<(Poly const& _this, Poly 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::value, int> = 0> bool operator>(Poly const& _this, Poly const& that) { return that < _this; } template < class I1, class I2, std::enable_if_t::value, int> = 0> bool operator<=(Poly const& _this, Poly const& that) { return !(that < _this); } template < class I1, class I2, std::enable_if_t::value, int> = 0> bool operator>=(Poly const& _this, Poly const& that) { return !(_this < that); } namespace poly { /** * A `Poly` interface for types that are move-only. */ struct IMoveOnly : PolyExtends<> { template 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 {}; } // namespace poly } // namespace folly