90 lines
3.1 KiB
C++
90 lines
3.1 KiB
C++
/*
|
|
* 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
|