Google OR-Tools v9.15
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
tagged_id.h
Go to the documentation of this file.
1// Copyright 2010-2025 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14#ifndef ORTOOLS_MATH_OPT_ELEMENTAL_TAGGED_ID_H_
15#define ORTOOLS_MATH_OPT_ELEMENTAL_TAGGED_ID_H_
16
17#include <cstddef>
18#include <cstdint>
19#include <iterator>
20#include <ostream>
21#include <string>
22#include <utility>
23#include <vector>
24
25#include "absl/base/attributes.h"
26#include "absl/log/check.h"
27#include "absl/strings/str_format.h"
28
30
31// A strongly typed int64_t where the tag is an a non-type template parameter
32// (e.g. an enum value or an int).
33//
34// An id of -1 corresponds to an invalid id and is the result of the default
35// constructor, otherwise, negative values are not allowed.
36//
37// The << operator must be defined for `tag`.
38template <auto tag>
39class TaggedId {
40 public:
41 // Constructs an invalid element id.
42 constexpr TaggedId() : id_(-1) {}
43
44 // Constructs a valid element id. `DCHECK`s that id is non-negative.
45 constexpr explicit TaggedId(int64_t id) : id_(id) {
46 CHECK_GE(id, 0) << "negative " << tag << " id: " << id;
47 }
48
49 constexpr bool IsValid() const { return id_ >= 0; }
50
51 // Returns the raw id value.
52 int64_t value() const { return id_; }
53
54 static constexpr auto tag_value() { return tag; }
55
56 friend bool operator==(const TaggedId& lhs, const TaggedId& rhs) {
57 return lhs.id_ == rhs.id_;
58 }
59
60 friend bool operator!=(const TaggedId& lhs, const TaggedId& rhs) {
61 return lhs.id_ != rhs.id_;
62 }
63
64 friend bool operator<(const TaggedId& lhs, const TaggedId& rhs) {
65 return lhs.id_ < rhs.id_;
66 }
67
68 friend bool operator<=(const TaggedId& lhs, const TaggedId& rhs) {
69 return lhs.id_ <= rhs.id_;
70 }
71
72 friend bool operator>(const TaggedId& lhs, const TaggedId& rhs) {
73 return lhs.id_ > rhs.id_;
74 }
75
76 friend bool operator>=(const TaggedId& lhs, const TaggedId& rhs) {
77 return lhs.id_ >= rhs.id_;
78 }
79
80 // We don't support addition between `TaggedId`s: what does it mean to add
81 // indices? We do support getting the next element id though.
82 TaggedId Next() const {
83 DCHECK(IsValid());
84 return TaggedId(id_ + 1);
85 }
86
87 // `MakeStrongIntRange()` relies on `operator++` being present. Prefer the
88 // more explicit `Next()` in general.
90 DCHECK(IsValid());
91 ++id_;
92 return *this;
93 }
94
95 template <typename H>
96 friend H AbslHashValue(H h, const TaggedId& a) {
97 return H::combine(std::move(h), a.id_);
98 }
99
100 using ValueType = int64_t; // Support for `StrongVector<TaggedId<tag>>`.
101
102 private:
103 int64_t id_;
104};
105
106template <auto tag>
107std::string ToString(const TaggedId<tag>& id) {
108 if (id.IsValid()) {
109 return absl::StrFormat("%s{%i}", absl::FormatStreamed(id.tag_value()),
110 id.value());
111 } else {
112 return absl::StrFormat("%s{invalid}", absl::FormatStreamed(id.tag_value()));
113 }
114}
115
116template <auto tag>
117std::ostream& operator<<(std::ostream& ostr, const TaggedId<tag>& id) {
118 ostr << ToString(id);
119 return ostr;
120}
121
122template <typename Sink, auto tag>
123void AbslStringify(Sink& sink, const TaggedId<tag>& id) {
124 sink.Append(ToString(id));
125}
126
127// An adaptor to expose a sequential container of `int64_t` as strongly typed
128// ids.
129//
130// Does not own the container.
131template <auto tag, typename Container>
133 public:
135
137 const Container* container ABSL_ATTRIBUTE_LIFETIME_BOUND)
138 : container_(*container) {}
139
140 size_t size() const { return container_.size(); }
141 bool empty() const { return container_.empty(); }
142
143 TaggedId<tag> operator[](size_t i) const {
144 return TaggedId<tag>(container_[i]);
145 }
146
147 auto begin() const { return Iterator(container_.begin()); }
148 auto end() const { return Iterator(container_.end()); }
149
150 private:
151 class Iterator final {
152 public:
153 using difference_type = std::ptrdiff_t;
155
156 Iterator() = default;
157 explicit Iterator(typename Container::const_iterator it) : it_(it) {}
158
159 value_type operator*() const { return value_type(*it_); }
160
161 Iterator& operator++() {
162 ++it_;
163 return *this;
164 }
165
166 Iterator operator++(int) {
167 auto tmp = *this;
168 ++*this;
169 return tmp;
170 }
171
172 friend bool operator==(const Iterator& lhs, const Iterator& rhs) {
173 return lhs.it_ == rhs.it_;
174 }
175 friend bool operator!=(const Iterator& lhs, const Iterator& rhs) {
176 return lhs.it_ != rhs.it_;
177 }
178
179 private:
180 typename Container::const_iterator it_ = {};
181 };
182#if __cplusplus >= 202002L
183 static_assert(std::forward_iterator<Iterator>);
184#endif
185
186 const Container& container_;
187};
188
189// A container that exposes a container of `int64_t` as strongly typed ids.
190template <auto tag>
191class TaggedIdsVector final {
192 public:
193 using Container = std::vector<int64_t>;
195 using value_type = typename View::value_type;
196
198 : container_(std::move(container)) {}
199
200 // This is move-constructible only.
202
203 View view() const { return View(&container_); }
204
205 size_t size() const { return container_.size(); }
206 bool empty() const { return container_.empty(); }
207
208 TaggedId<tag> operator[](size_t i) const {
209 return TaggedId<tag>(container_[i]);
210 }
211
212 auto begin() const { return view().begin(); }
213 auto end() const { return view().end(); }
214
218
219 // Provides access to the untyped container.
220 Container& container() { return container_; }
221
222 private:
223 Container container_;
224};
225
226template <auto tag>
228
229} // namespace operations_research::math_opt
230
231#endif // ORTOOLS_MATH_OPT_ELEMENTAL_TAGGED_ID_H_
friend bool operator>(const TaggedId &lhs, const TaggedId &rhs)
Definition tagged_id.h:72
friend bool operator==(const TaggedId &lhs, const TaggedId &rhs)
Definition tagged_id.h:56
friend H AbslHashValue(H h, const TaggedId &a)
Definition tagged_id.h:96
friend bool operator>=(const TaggedId &lhs, const TaggedId &rhs)
Definition tagged_id.h:76
friend bool operator<(const TaggedId &lhs, const TaggedId &rhs)
Definition tagged_id.h:64
friend bool operator<=(const TaggedId &lhs, const TaggedId &rhs)
Definition tagged_id.h:68
friend bool operator!=(const TaggedId &lhs, const TaggedId &rhs)
Definition tagged_id.h:60
TaggedId< tag > operator[](size_t i) const
Definition tagged_id.h:143
TaggedIdsConstView(const Container *container ABSL_ATTRIBUTE_LIFETIME_BOUND)
Definition tagged_id.h:136
TaggedIdsVector(const TaggedIdsVector &container)=delete
TaggedIdsVector & operator=(TaggedIdsVector &&container)=delete
TaggedIdsVector(TaggedIdsVector &&) noexcept=default
TaggedIdsVector & operator=(const TaggedIdsVector &container)=delete
TaggedId< tag > operator[](size_t i) const
Definition tagged_id.h:208
When the underlying default is used When the feature cannot be turned kOff will return an error If the feature is enabled by default
Definition parameters.h:180
typename TaggedIdsVector< tag >::View TaggedIdsSpan
Definition tagged_id.h:227
void AbslStringify(Sink &sink, const RemoteStreamingSolveMode mode)
std::ostream & operator<<(std::ostream &ostr, const SecondOrderConeConstraint &constraint)
absl::string_view ToString(const AttrT attr)
Definition attributes.h:327
LinearExpr operator*(LinearExpr lhs, double rhs)
STL namespace.