1 /*
2  * Copyright 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 namespace android {
19 
20 template <typename T, template <typename> class AbilityType>
21 struct Ability {
baseAbility22     T& base() { return static_cast<T&>(*this); }
baseAbility23     T const& base() const { return static_cast<T const&>(*this); }
24 };
25 
26 template <typename T>
27 struct Add : Ability<T, Add> {
28     inline T operator+(T const& other) const { return T(this->base().value() + other.value()); }
29     inline T& operator++() {
30         ++this->base().value();
31         return this->base();
32     };
33     inline T operator++(int) {
34         T tmp(this->base());
35         operator++();
36         return tmp;
37     };
38     inline T& operator+=(T const& other) {
39         this->base().value() += other.value();
40         return this->base();
41     };
42 };
43 
44 template <typename T>
45 struct Compare : Ability<T, Compare> {
46     inline bool operator==(T const& other) const { return this->base().value() == other.value(); };
47     inline bool operator<(T const& other) const { return this->base().value() < other.value(); }
48     inline bool operator<=(T const& other) const { return (*this < other) || (*this == other); }
49     inline bool operator!=(T const& other) const { return !(*this == other); }
50     inline bool operator>=(T const& other) const { return !(*this < other); }
51     inline bool operator>(T const& other) const { return !(*this < other || *this == other); }
52 };
53 
54 template <typename T>
55 struct Hash : Ability<T, Hash> {
hashHash56     [[nodiscard]] std::size_t hash() const {
57         return std::hash<typename std::remove_const<
58                 typename std::remove_reference<decltype(this->base().value())>::type>::type>{}(
59                 this->base().value());
60     }
61 };
62 
63 template <typename T, typename W, template <typename> class... Ability>
64 struct StrongTyping : Ability<StrongTyping<T, W, Ability...>>... {
StrongTypingStrongTyping65     StrongTyping() : mValue(0) {}
StrongTypingStrongTyping66     explicit StrongTyping(T const& value) : mValue(value) {}
67     StrongTyping(StrongTyping const&) = default;
68     StrongTyping& operator=(StrongTyping const&) = default;
TStrongTyping69     explicit inline operator T() const { return mValue; }
valueStrongTyping70     T const& value() const { return mValue; }
valueStrongTyping71     T& value() { return mValue; }
72 
73 private:
74     T mValue;
75 };
76 } // namespace android
77 
78 namespace std {
79 template <typename T, typename W, template <typename> class... Ability>
80 struct hash<android::StrongTyping<T, W, Ability...>> {
81     std::size_t operator()(android::StrongTyping<T, W, Ability...> const& k) const {
82         return k.hash();
83     }
84 };
85 } // namespace std
86