/* * Copyright 2019 The Android Open Source Project * * 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 namespace android { template class AbilityType> struct Ability { T& base() { return static_cast(*this); } T const& base() const { return static_cast(*this); } }; template struct Add : Ability { inline T operator+(T const& other) const { return T(this->base().value() + other.value()); } inline T& operator++() { ++this->base().value(); return this->base(); }; inline T operator++(int) { T tmp(this->base()); operator++(); return tmp; }; inline T& operator+=(T const& other) { this->base().value() += other.value(); return this->base(); }; }; template struct Compare : Ability { inline bool operator==(T const& other) const { return this->base().value() == other.value(); }; inline bool operator<(T const& other) const { return this->base().value() < other.value(); } inline bool operator<=(T const& other) const { return (*this < other) || (*this == other); } inline bool operator!=(T const& other) const { return !(*this == other); } inline bool operator>=(T const& other) const { return !(*this < other); } inline bool operator>(T const& other) const { return !(*this < other || *this == other); } }; template struct Hash : Ability { [[nodiscard]] std::size_t hash() const { return std::hashbase().value())>::type>::type>{}( this->base().value()); } }; template class... Ability> struct StrongTyping : Ability>... { constexpr StrongTyping() = default; constexpr explicit StrongTyping(T const& value) : mValue(value) {} StrongTyping(StrongTyping const&) = default; StrongTyping& operator=(StrongTyping const&) = default; explicit inline operator T() const { return mValue; } T const& value() const { return mValue; } T& value() { return mValue; } friend std::ostream& operator<<(std::ostream& os, const StrongTyping& value) { return os << value.value(); } private: T mValue{0}; }; } // namespace android namespace std { template class... Ability> struct hash> { std::size_t operator()(android::StrongTyping const& k) const { return k.hash(); } }; } // namespace std