carl  24.04
Computer ARithmetic Library
streamingOperators.h
Go to the documentation of this file.
1 /**
2  * @file streamingOperators.h
3  * @author Gereon Kremer <gereon.kremer@cs.rwth-aachen.de>
4  *
5  * This file contains streaming operators for most of the STL containers.
6  */
7 
8 #pragma once
9 
10 #include <cassert>
11 #include <forward_list>
12 #include <iostream>
13 #include <list>
14 #include <map>
15 #include <optional>
16 #include <set>
17 #include <tuple>
18 #include <unordered_map>
19 #include <unordered_set>
20 #include <utility>
21 #include <variant>
22 #include <vector>
23 #include <deque>
24 #include "boost/container/flat_set.hpp"
25 #include "boost/container/flat_map.hpp"
26 
27 namespace carl {
28 
29 template<typename T>
30 inline std::ostream& operator<<(std::ostream& os, const std::forward_list<T>& l);
31 template<typename T>
32 inline std::ostream& operator<<(std::ostream& os, const std::initializer_list<T>& l);
33 template<typename T>
34 inline std::ostream& operator<<(std::ostream& os, const std::list<T>& l);
35 template<typename Key, typename Value, typename Comparator>
36 inline std::ostream& operator<<(std::ostream& os, const std::map<Key, Value, Comparator>& m);
37 template<typename Key, typename Value, typename Comparator>
38 inline std::ostream& operator<<(std::ostream& os, const std::multimap<Key, Value, Comparator>& m);
39 template<typename T>
40 inline std::ostream& operator<<(std::ostream& os, const std::optional<T>& o);
41 template<typename U, typename V>
42 inline std::ostream& operator<<(std::ostream& os, const std::pair<U, V>& p);
43 template<typename T, typename C>
44 inline std::ostream& operator<<(std::ostream& os, const std::set<T, C>& s);
45 template<typename... T>
46 std::ostream& operator<<(std::ostream& os, const std::tuple<T...>& t);
47 template<typename Key, typename Value, typename H, typename E, typename A>
48 inline std::ostream& operator<<(std::ostream& os, const std::unordered_map<Key, Value, H, E, A>& m);
49 template<typename T, typename H, typename K, typename A>
50 inline std::ostream& operator<<(std::ostream& os, const std::unordered_set<T, H, K, A>& s);
51 template<typename T, typename... Tail>
52 inline std::ostream& operator<<(std::ostream& os, const std::variant<T, Tail...>& v);
53 template<typename T>
54 inline std::ostream& operator<<(std::ostream& os, const std::vector<T>& v);
55 template<typename T>
56 inline std::ostream& operator<<(std::ostream& os, const std::deque<T>& v);
57 
58 /**
59  * Allows to easily output some container with all elements separated by some string.
60  * Usage: `os << stream_joined(" ", container)`.
61  * @param glue The intermediate string.
62  * @param v The container to be printed.
63  * @return A temporary object that implements `operator<<()`.
64  */
65 template<typename T>
66 inline auto stream_joined(const std::string& glue, const T& v);
67 
68 /**
69  * Allows to easily output some container with all elements separated by some string.
70  * An additional callable `f` takes care of writing an individual element to the stream.
71  * Usage: `os << stream_joined(" ", container)`.
72  * @param glue The intermediate string.
73  * @param v The container to be printed.
74  * @param f A callable taking a stream and an element of `v`.
75  * @return A temporary object that implements `operator<<()`.
76  */
77 template<typename T, typename F>
78 inline auto stream_joined(const std::string& glue, const T& v, F&& f);
79 
80 
81 /**
82  * Output a std::forward_list with arbitrary content.
83  * The format is `[<item>, <item>, ...]`
84  * @param os Output stream.
85  * @param l list to be printed.
86  * @return Output stream.
87  */
88 template<typename T>
89 inline std::ostream& operator<<(std::ostream& os, const std::forward_list<T>& l) {
90  return os << "[" << stream_joined(", ", l) << "]";
91 }
92 
93 /**
94  * Output a std::initializer_list with arbitrary content.
95  * The format is `[<item>, <item>, ...]`
96  * @param os Output stream.
97  * @param l list to be printed.
98  * @return Output stream.
99  */
100 template<typename T>
101 inline std::ostream& operator<<(std::ostream& os, const std::initializer_list<T>& l) {
102  return os << "[" << stream_joined(", ", l) << "]";
103 }
104 
105 /**
106  * Output a std::list with arbitrary content.
107  * The format is `[<length>: <item>, <item>, ...]`
108  * @param os Output stream.
109  * @param l list to be printed.
110  * @return Output stream.
111  */
112 template<typename T>
113 inline std::ostream& operator<<(std::ostream& os, const std::list<T>& l) {
114  return os << "[" << l.size() << ": " << stream_joined(", ", l) << "]";
115 }
116 
117 /**
118  * Output a std::map with arbitrary content.
119  * The format is `{<key>:<value>, <key>:<value>, ...}`
120  * @param os Output stream.
121  * @param m map to be printed.
122  * @return Output stream.
123  */
124 template<typename Key, typename Value, typename Comparator>
125 inline std::ostream& operator<<(std::ostream& os, const std::map<Key, Value, Comparator>& m) {
126  return os << "{" << stream_joined(", ", m, [](auto& o, const auto& p){ o << p.first << " : " << p.second; }) << "}";
127 }
128 
129 /**
130  * Output a std::multimap with arbitrary content.
131  * The format is `{<key>:<value>, <key>:<value>, ...}`
132  * @param os Output stream.
133  * @param m multimap to be printed.
134  * @return Output stream.
135  */
136 template<typename Key, typename Value, typename Comparator>
137 inline std::ostream& operator<<(std::ostream& os, const std::multimap<Key, Value, Comparator>& m) {
138  return os << "{" << stream_joined(", ", m, [](auto& o, const auto& p){ o << p.first << " : " << p.second; }) << "}";
139 }
140 
141 /**
142  * Output a std::optional with arbitrary content.
143  * Prints `empty` if the optional holds no value and forwards the call to the content otherwise.
144  * @param os Output stream.
145  * @param o optional to be printed.
146  * @return Output stream.
147  */
148 template<typename T>
149 inline std::ostream& operator<<(std::ostream& os, const std::optional<T>& o) {
150  if (o.has_value()) return os << *o;
151  return os << "empty";
152 }
153 
154 /**
155  * Output a std::pair with arbitrary content.
156  * The format is `(<first>, <second>)`
157  * @param os Output stream.
158  * @param p pair to be printed.
159  * @return Output stream.
160  */
161 template<typename U, typename V>
162 inline std::ostream& operator<<(std::ostream& os, const std::pair<U, V>& p) {
163  return os << "(" << p.first << ", " << p.second << ")";
164 }
165 
166 /**
167  * Output a std::set with arbitrary content.
168  * The format is `{<length>: <item>, <item>, ...}`
169  * @param os Output stream.
170  * @param s set to be printed.
171  * @return Output stream.
172  */
173 template<typename T, typename C>
174 inline std::ostream& operator<<(std::ostream& os, const std::set<T, C>& s) {
175  return os << "{" << s.size() << ": " << stream_joined(", ", s) << "}";
176 }
177 
178 /**
179  * Output a boost::container::flat_set with arbitrary content.
180  * The format is `{<length>: <item>, <item>, ...}`
181  * @param os Output stream.
182  * @param s set to be printed.
183  * @return Output stream.
184  */
185 template<typename T, typename C>
186 inline std::ostream& operator<<(std::ostream& os, const boost::container::flat_set<T, C>& s) {
187  return os << "{" << s.size() << ": " << stream_joined(", ", s) << "}";
188 }
189 
190 namespace detail {
191 /**
192  * Helper function that actually outputs a std::tuple.
193  * The format is `(<item>, <item>, ...)`
194  * @param os Output stream.
195  * @param t tuple to be printed.
196  * @return Output stream.
197  */
198 template<typename Tuple, std::size_t... I>
199 std::ostream& stream_tuple_impl(std::ostream& os, const Tuple& t, std::index_sequence<I...>) {
200  (..., (os << (I == 0 ? "(" : ", ") << std::get<I>(t)));
201  return os << ")";
202 }
203 }
204 
205 /**
206  * Output a std::tuple with arbitrary content.
207  * The format is `(<item>, <item>, ...)`
208  * @param os Output stream.
209  * @param t tuple to be printed.
210  * @return Output stream.
211  */
212 template<typename... T>
213 std::ostream& operator<<(std::ostream& os, const std::tuple<T...>& t) {
214  return detail::stream_tuple_impl(os, t, std::make_index_sequence<sizeof...(T)>());
215 }
216 
217 /**
218  * Output a std::unordered_map with arbitrary content.
219  * The format is `{<key>:<value>, <key>:<value>, ...}`
220  * @param os Output stream.
221  * @param m map to be printed.
222  * @return Output stream.
223  */
224 template<typename Key, typename Value, typename H, typename E, typename A>
225 inline std::ostream& operator<<(std::ostream& os, const std::unordered_map<Key, Value, H, E, A>& m) {
226  return os << "{" << stream_joined(", ", m, [](auto& o, const auto& p){ o << p.first << " : " << p.second; }) << "}";
227 }
228 
229 /**
230  * Output a boost::container::flat_map with arbitrary content.
231  * The format is `{<key>:<value>, <key>:<value>, ...}`
232  * @param os Output stream.
233  * @param m map to be printed.
234  * @return Output stream.
235  */
236 template<class Key, class T, class Compare, class AllocatorOrContainer>
237 inline std::ostream& operator<<(std::ostream& os, const boost::container::flat_map<Key, T, Compare, AllocatorOrContainer>& m) {
238  return os << "{" << stream_joined(", ", m, [](auto& o, const auto& p){ o << p.first << " : " << p.second; }) << "}";
239 }
240 
241 /**
242  * Output a std::unordered_set with arbitrary content.
243  * The format is `{<length>: <item>, <item>, ...}`
244  * @param os Output stream.
245  * @param s unordered_set to be printed.
246  * @return Output stream.
247  */
248 template<typename T, typename H, typename K, typename A>
249 inline std::ostream& operator<<(std::ostream& os, const std::unordered_set<T, H, K, A>& s) {
250  return os << "{" << s.size() << ": " << stream_joined(", ", s) << "}";
251 }
252 
253 /**
254  * Output a std::variant with arbitrary content.
255  * The call is simply forwarded to whatever content is currently stored in the variant.
256  * @param os Output stream.
257  * @param v variant to be printed.
258  * @return Output stream.
259  */
260 template<typename T, typename... Tail>
261 inline std::ostream& operator<<(std::ostream& os, const std::variant<T, Tail...>& v) {
262  return std::visit([&os](const auto& value) -> auto& { return os << value; }, v);
263 }
264 
265 /**
266  * Output a std::vector with arbitrary content.
267  * The format is `[<length>: <item>, <item>, ...]`
268  * @param os Output stream.
269  * @param v vector to be printed.
270  * @return Output stream.
271  */
272 template<typename T>
273 inline std::ostream& operator<<(std::ostream& os, const std::vector<T>& v) {
274  return os << "[" << v.size() << ": " << stream_joined(", ", v) << "]";
275 }
276 
277 /**
278  * Output a std::deque with arbitrary content.
279  * The format is `[<length>: <item>, <item>, ...]`
280  * @param os Output stream.
281  * @param v vector to be printed.
282  * @return Output stream.
283  */
284 template<typename T>
285 inline std::ostream& operator<<(std::ostream& os, const std::deque<T>& v) {
286  return os << "[" << v.size() << ": " << stream_joined(", ", v) << "]";
287 }
288 
289 namespace detail {
290  template<typename T, typename F>
292  std::string glue;
293  const T& values;
295  };
296  template<typename T, typename F>
297  std::ostream& operator<<(std::ostream& os, const stream_joined_impl<T,F>& sji) {
298  auto it = sji.values.begin();
299  if (it == sji.values.end()) {
300  return os;
301  }
302  sji.callable(os, *it);
303  for (++it; it != sji.values.end(); ++it) {
304  os << sji.glue;
305  sji.callable(os, *it);
306  }
307  return os;
308  }
309 }
310 template<typename T>
311 inline auto stream_joined(const std::string& glue, const T& v) {
312  auto f = [](auto& os, const auto& t){ os << t; };
313  return detail::stream_joined_impl<T, decltype(f)>{glue, v, f};
314 }
315 
316 template<typename T, typename F>
317 inline auto stream_joined(const std::string& glue, const T& v, F&& f) {
318  return detail::stream_joined_impl<T,F>{glue, v, std::forward<F>(f)};
319 }
320 
321 }
carl is the main namespace for the library.
std::ostream & operator<<(std::ostream &os, const BasicConstraint< Poly > &c)
Prints the given constraint on the given stream.
void visit(const Formula< Pol > &formula, Visitor func)
Recursively calls func on every subformula.
Definition: Visit.h:12
auto stream_joined(const std::string &glue, const T &v)
Allows to easily output some container with all elements separated by some string.
std::ostream & stream_tuple_impl(std::ostream &os, const Tuple &t, std::index_sequence< I... >)
Helper function that actually outputs a std::tuple.
std::ostream & operator<<(std::ostream &os, const stream_joined_impl< T, F > &sji)