Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
stl_logging.h
Go to the documentation of this file.
1// Copyright 2010-2024 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 OR_TOOLS_BASE_STL_LOGGING_H_
15#define OR_TOOLS_BASE_STL_LOGGING_H_
16
17#include <deque>
18#include <list>
19#include <map>
20#include <ostream>
21#include <set>
22#include <utility>
23#include <vector>
24
25#include "absl/container/flat_hash_map.h"
26#include "absl/container/flat_hash_set.h"
27#include "absl/container/node_hash_map.h"
28#include "absl/container/node_hash_set.h"
29
30// Forward declare these two, and define them after all the container streams
31// operators so that we can recurse from pair -> container -> container -> pair
32// properly.
33template <class First, class Second>
34std::ostream& operator<<(std::ostream& out, const std::pair<First, Second>& p);
35
36namespace google {
37
38template <class Iter>
39void PrintSequence(std::ostream& out, Iter begin, Iter end);
40
41} // namespace google
42
43#define OUTPUT_TWO_ARG_CONTAINER(Sequence) \
44 template <class T1, class T2> \
45 inline std::ostream& operator<<(std::ostream& out, \
46 const Sequence<T1, T2>& seq) { \
47 google::PrintSequence(out, seq.begin(), seq.end()); \
48 return out; \
49 }
50
51OUTPUT_TWO_ARG_CONTAINER(std::vector)
54
55#undef OUTPUT_TWO_ARG_CONTAINER
56
57#define OUTPUT_THREE_ARG_CONTAINER(Sequence) \
58 template <class T1, class T2, class T3> \
59 inline std::ostream& operator<<(std::ostream& out, \
60 const Sequence<T1, T2, T3>& seq) { \
61 google::PrintSequence(out, seq.begin(), seq.end()); \
62 return out; \
63 }
64
66OUTPUT_THREE_ARG_CONTAINER(std::multiset)
67
68#undef OUTPUT_THREE_ARG_CONTAINER
69
70#define OUTPUT_FOUR_ARG_CONTAINER(Sequence) \
71 template <class T1, class T2, class T3, class T4> \
72 inline std::ostream& operator<<(std::ostream& out, \
73 const Sequence<T1, T2, T3, T4>& seq) { \
74 google::PrintSequence(out, seq.begin(), seq.end()); \
75 return out; \
76 }
77
79OUTPUT_FOUR_ARG_CONTAINER(std::multimap)
80OUTPUT_FOUR_ARG_CONTAINER(absl::flat_hash_set)
81OUTPUT_FOUR_ARG_CONTAINER(absl::node_hash_set)
82
83#undef OUTPUT_FOUR_ARG_CONTAINER
84
85#define OUTPUT_FIVE_ARG_CONTAINER(Sequence) \
86 template <class T1, class T2, class T3, class T4, class T5> \
87 inline std::ostream& operator<<(std::ostream& out, \
88 const Sequence<T1, T2, T3, T4, T5>& seq) { \
89 google::PrintSequence(out, seq.begin(), seq.end()); \
90 return out; \
91 }
92
93OUTPUT_FIVE_ARG_CONTAINER(absl::flat_hash_map)
94OUTPUT_FIVE_ARG_CONTAINER(absl::node_hash_map)
95
96#undef OUTPUT_FIVE_ARG_CONTAINER
97
98template <class First, class Second>
99inline std::ostream& operator<<(std::ostream& out,
100 const std::pair<First, Second>& p) {
101 out << '(' << p.first << ", " << p.second << ')';
102 return out;
103}
104
105namespace google {
106
107template <class Iter>
108inline void PrintSequence(std::ostream& out, Iter begin, Iter end) {
109 // Output at most 100 elements -- appropriate if used for logging.
110 for (int i = 0; begin != end && i < 100; ++i, ++begin) {
111 if (i > 0) out << ' ';
112 out << *begin;
113 }
114 if (begin != end) {
115 out << " ...";
116 }
117}
118
119} // namespace google
120
121// Note that this is technically undefined behavior! We are adding things into
122// the std namespace for a reason though -- we are providing new operations on
123// types which are themselves defined with this namespace. Without this, these
124// operator overloads cannot be found via ADL. If these definitions are not
125// found via ADL, they must be #included before they're used, which requires
126// this header to be included before apparently independent other headers.
127//
128// For example, base/logging.h defines various template functions to implement
129// CHECK_EQ(x, y) and stream x and y into the log in the event the check fails.
130// It does so via the function template MakeCheckOpValueString:
131// template<class T>
132// void MakeCheckOpValueString(strstream* ss, const T& v) {
133// (*ss) << v;
134// }
135// Because 'logging.h' is included before 'stl_logging.h',
136// subsequent CHECK_EQ(v1, v2) for vector<...> typed variable v1 and v2 can only
137// find these operator definitions via ADL.
138//
139// Even this solution has problems -- it may pull unintended operators into the
140// namespace as well, allowing them to also be found via ADL, and creating code
141// that only works with a particular order of includes. Long term, we need to
142// move all of the *definitions* into namespace std, bet we need to ensure no
143// one references them first. This lets us take that step. We cannot define them
144// in both because that would create ambiguous overloads when both are found.
145namespace std {
146using ::operator<<;
147}
148
149#endif // OR_TOOLS_BASE_STL_LOGGING_H_
void PrintSequence(std::ostream &out, Iter begin, Iter end)
STL namespace.
std::optional< int64_t > end
#define OUTPUT_FOUR_ARG_CONTAINER(Sequence)
Definition stl_logging.h:70
#define OUTPUT_TWO_ARG_CONTAINER(Sequence)
Definition stl_logging.h:43
std::ostream & operator<<(std::ostream &out, const std::pair< First, Second > &p)
Definition stl_logging.h:99
#define OUTPUT_THREE_ARG_CONTAINER(Sequence)
Definition stl_logging.h:57
#define OUTPUT_FIVE_ARG_CONTAINER(Sequence)
Definition stl_logging.h:85