EtcPal  HEAD (unstable)
ETC Platform Abstraction Layer (EtcPal)
View other versions:
opaque_id.h
Go to the documentation of this file.
1 /******************************************************************************
2  * Copyright 2022 ETC Inc.
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  * This file is a part of EtcPal. For more information, go to:
17  * https://github.com/ETCLabs/EtcPal
18  ******************************************************************************/
19 
22 
23 #ifndef ETCPAL_CPP_OPAQUE_ID_H_
24 #define ETCPAL_CPP_OPAQUE_ID_H_
25 
26 #include <functional>
27 #include "etcpal/cpp/common.h"
28 
29 namespace etcpal
30 {
34 
116 template <class IdType, class ValueType, ValueType InvalidValue>
117 class OpaqueId
118 {
119 public:
120  OpaqueId() = default;
121  constexpr explicit OpaqueId(ValueType value);
122 
123  static constexpr OpaqueId Invalid();
124 
125  constexpr ValueType value() const;
126  constexpr bool IsValid() const;
127  constexpr explicit operator bool() const;
128  constexpr bool operator!() const;
129 
130  ETCPAL_CONSTEXPR_14 void SetValue(const ValueType& new_value);
131  ETCPAL_CONSTEXPR_14 void Clear();
132 
133 private:
134  ValueType value_{InvalidValue};
135 };
136 
145 template <class IdType, class ValueType, ValueType InvalidValue>
147 {
148  return OpaqueId();
149 }
150 
152 template <class IdType, class ValueType, ValueType InvalidValue>
153 constexpr OpaqueId<IdType, ValueType, InvalidValue>::OpaqueId(ValueType value) : value_(value)
154 {
155 }
156 
158 template <class IdType, class ValueType, ValueType InvalidValue>
160 {
161  return value_;
162 }
163 
165 template <class IdType, class ValueType, ValueType InvalidValue>
167 {
168  return !(value_ == InvalidValue);
169 }
170 
184 template <class IdType, class ValueType, ValueType InvalidValue>
186 {
187  return IsValid();
188 }
189 
191 template <class IdType, class ValueType, ValueType InvalidValue>
193 {
194  return !IsValid();
195 }
196 
199 template <class IdType, class ValueType, ValueType InvalidValue>
201 {
202  value_ = new_value;
203 }
204 
207 template <class IdType, class ValueType, ValueType InvalidValue>
209 {
210  value_ = InvalidValue;
211 }
212 
215 
218 
219 template <class IdType, class ValueType, ValueType InvalidValue>
220 constexpr bool operator==(const OpaqueId<IdType, ValueType, InvalidValue>& a,
222 {
223  return a.value() == b.value();
224 }
225 
226 template <class IdType, class ValueType, ValueType InvalidValue>
227 constexpr bool operator!=(const OpaqueId<IdType, ValueType, InvalidValue>& a,
228  const OpaqueId<IdType, ValueType, InvalidValue>& b)
229 {
230  return !(a == b);
231 }
232 
235 
236 }; // namespace etcpal
237 
239 
240 namespace std
241 {
242 // Inject a std::less specialization for any template specialization for OpaqueId. This takes the
243 // place of operator< for the purposes of OpaqueId usage in ordered containers. We don't provide
244 // relational operators other than == and != to avoid the temptation to treat OpaqueIds like
245 // numbers.
246 template <class IdType, class ValueType, ValueType InvalidValue>
247 struct less<::etcpal::OpaqueId<IdType, ValueType, InvalidValue>>
248 {
249  ETCPAL_CONSTEXPR_14 bool operator()(const ::etcpal::OpaqueId<IdType, ValueType, InvalidValue>& a,
250  const ::etcpal::OpaqueId<IdType, ValueType, InvalidValue>& b) const
251  {
252  return a.value() < b.value();
253  }
254 };
255 
256 // Inject a new std::hash specialization for any template specialization of OpaqueId, so that
257 // OpaqueIds can be used in hash-based containers (e.g. unordered_map and unordered_set) without
258 // a user needing to create a hash specialization.
259 //
260 // The std::hash specialization simply passes through to a hash of the underlying value. If the
261 // underlying value is not hashable, this specialization should simply be eliminated without a
262 // compile error through SFINAE.
263 template <class IdType, class ValueType, ValueType InvalidValue>
264 struct hash<::etcpal::OpaqueId<IdType, ValueType, InvalidValue>>
265 {
266  std::size_t operator()(const ::etcpal::OpaqueId<IdType, ValueType, InvalidValue>& id) const noexcept
267  {
268  return std::hash<ValueType>()(id.value());
269  }
270 };
271 }; // namespace std
272 
274 
275 #endif // ETCPAL_CPP_OPAQUE_ID_H_
A strongly-typed ID with arbitrary internal representation.
Definition: opaque_id.h:118
static constexpr OpaqueId Invalid()
Explicitly create an invalid ID.
Definition: opaque_id.h:146
ETCPAL_CONSTEXPR_14 void Clear()
Clear any valid value from an ID and set it back to the invalid value.
Definition: opaque_id.h:208
ETCPAL_CONSTEXPR_14 void SetValue(const ValueType &new_value)
Set a new underlying value for an ID.
Definition: opaque_id.h:200
constexpr bool IsValid() const
Explicitly determine whether an ID is valid.
Definition: opaque_id.h:166
constexpr bool operator!() const
Determine whether an ID is not valid.
Definition: opaque_id.h:192
constexpr ValueType value() const
Get the underlying value from an ID.
Definition: opaque_id.h:159
Common definitions used by EtcPal C++ wrappers.
#define ETCPAL_CONSTEXPR_14
Stand-in for "constexpr" on entities that can only be defined "constexpr" in C++14 or later.
Definition: common.h:53
#define ETCPAL_CONSTEXPR_14_OR_INLINE
Defined to "constexpr" in C++14 or later, "inline" earlier.
Definition: common.h:54