blob: a05c12395610df69ae1238afd12285559629f91e [file] [log] [blame]
/*
* 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 <typename T, template <typename> class AbilityType>
struct Ability {
T& base() { return static_cast<T&>(*this); }
T const& base() const { return static_cast<T const&>(*this); }
};
template <typename T>
struct Add : Ability<T, Add> {
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 <typename T>
struct Compare : Ability<T, Compare> {
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 <typename T>
struct Hash : Ability<T, Hash> {
[[nodiscard]] std::size_t hash() const {
return std::hash<typename std::remove_const<
typename std::remove_reference<decltype(this->base().value())>::type>::type>{}(
this->base().value());
}
};
template <typename T, typename W, template <typename> class... Ability>
struct StrongTyping : Ability<StrongTyping<T, W, 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<T, W, Ability...>& value) {
return os << value.value();
}
private:
T mValue{0};
};
} // namespace android
namespace std {
template <typename T, typename W, template <typename> class... Ability>
struct hash<android::StrongTyping<T, W, Ability...>> {
std::size_t operator()(android::StrongTyping<T, W, Ability...> const& k) const {
return k.hash();
}
};
} // namespace std