File indexing completed on 2025-01-18 09:54:50
0001
0002
0003
0004
0005
0006
0007
0008 #pragma once
0009
0010 #include <cstddef>
0011 #include <functional>
0012 #include <type_traits>
0013
0014 #include "Assert.hh"
0015 #include "Macros.hh"
0016 #include "Types.hh"
0017
0018 namespace celeritas
0019 {
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030 template<class ValueT, class SizeT = ::celeritas::size_type>
0031 class OpaqueId
0032 {
0033 static_assert(std::is_unsigned_v<SizeT> && !std::is_same_v<SizeT, bool>,
0034 "SizeT must be unsigned.");
0035
0036 public:
0037
0038
0039 using value_type = ValueT;
0040 using size_type = SizeT;
0041
0042
0043 public:
0044
0045 CELER_CONSTEXPR_FUNCTION OpaqueId() : value_(OpaqueId::invalid_value()) {}
0046
0047
0048 explicit CELER_CONSTEXPR_FUNCTION OpaqueId(size_type index) : value_(index)
0049 {
0050 }
0051
0052
0053 explicit CELER_CONSTEXPR_FUNCTION operator bool() const
0054 {
0055 return value_ != invalid_value();
0056 }
0057
0058
0059 CELER_FUNCTION OpaqueId& operator++()
0060 {
0061 CELER_EXPECT(*this);
0062 value_ += 1;
0063 return *this;
0064 }
0065
0066
0067 CELER_FUNCTION OpaqueId operator++(int)
0068 {
0069 OpaqueId old{*this};
0070 ++*this;
0071 return old;
0072 }
0073
0074
0075 CELER_FUNCTION OpaqueId& operator--()
0076 {
0077 CELER_EXPECT(*this && value_ > 0);
0078 value_ -= 1;
0079 return *this;
0080 }
0081
0082
0083 CELER_FUNCTION OpaqueId operator--(int)
0084 {
0085 OpaqueId old{*this};
0086 --*this;
0087 return old;
0088 }
0089
0090
0091 CELER_FORCEINLINE_FUNCTION size_type get() const
0092 {
0093 CELER_EXPECT(*this);
0094 return value_;
0095 }
0096
0097
0098 CELER_CONSTEXPR_FUNCTION size_type unchecked_get() const { return value_; }
0099
0100
0101 CELER_CONSTEXPR_FUNCTION size_type const* data() const { return &value_; }
0102
0103 private:
0104 size_type value_;
0105
0106
0107
0108
0109 static CELER_CONSTEXPR_FUNCTION size_type invalid_value()
0110 {
0111 return static_cast<size_type>(-1);
0112 }
0113 };
0114
0115
0116
0117
0118 #define CELER_DEFINE_OPAQUEID_CMP(TOKEN) \
0119 template<class V, class S> \
0120 CELER_CONSTEXPR_FUNCTION bool operator TOKEN(OpaqueId<V, S> lhs, \
0121 OpaqueId<V, S> rhs) \
0122 { \
0123 return lhs.unchecked_get() TOKEN rhs.unchecked_get(); \
0124 }
0125
0126
0127
0128 CELER_DEFINE_OPAQUEID_CMP(==)
0129 CELER_DEFINE_OPAQUEID_CMP(!=)
0130 CELER_DEFINE_OPAQUEID_CMP(<)
0131 CELER_DEFINE_OPAQUEID_CMP(>)
0132 CELER_DEFINE_OPAQUEID_CMP(<=)
0133 CELER_DEFINE_OPAQUEID_CMP(>=)
0134
0135
0136 #undef CELER_DEFINE_OPAQUEID_CMP
0137
0138
0139
0140 template<class V, class S, class U>
0141 CELER_CONSTEXPR_FUNCTION bool operator<(OpaqueId<V, S> lhs, U rhs)
0142 {
0143
0144 return lhs && (U(lhs.unchecked_get()) < rhs);
0145 }
0146
0147
0148
0149 template<class V, class S, class U>
0150 CELER_CONSTEXPR_FUNCTION bool operator<=(OpaqueId<V, S> lhs, U rhs)
0151 {
0152
0153 return lhs && (U(lhs.unchecked_get()) <= rhs);
0154 }
0155
0156
0157
0158 template<class V, class S>
0159 inline CELER_FUNCTION S operator-(OpaqueId<V, S> self, OpaqueId<V, S> other)
0160 {
0161 CELER_EXPECT(self);
0162 CELER_EXPECT(other);
0163 return self.unchecked_get() - other.unchecked_get();
0164 }
0165
0166
0167
0168 template<class V, class S>
0169 inline CELER_FUNCTION OpaqueId<V, S>
0170 operator+(OpaqueId<V, S> id, std::make_signed_t<S> offset)
0171 {
0172 CELER_EXPECT(id);
0173 CELER_EXPECT(offset >= 0 || static_cast<S>(-offset) <= id.unchecked_get());
0174 return OpaqueId<V, S>{id.unchecked_get() + static_cast<S>(offset)};
0175 }
0176
0177
0178
0179 template<class V, class S>
0180 inline CELER_FUNCTION OpaqueId<V, S>
0181 operator-(OpaqueId<V, S> id, std::make_signed_t<S> offset)
0182 {
0183 CELER_EXPECT(id);
0184 CELER_EXPECT(offset <= 0 || static_cast<S>(offset) <= id.unchecked_get());
0185 return OpaqueId<V, S>{id.unchecked_get() - static_cast<S>(offset)};
0186 }
0187
0188
0189 }
0190
0191
0192
0193 namespace std
0194 {
0195
0196 template<class V, class S>
0197 struct hash<celeritas::OpaqueId<V, S>>
0198 {
0199 std::size_t operator()(celeritas::OpaqueId<V, S> const& id) const noexcept
0200 {
0201 return std::hash<S>()(id.unchecked_get());
0202 }
0203 };
0204 }
0205