OR-Tools  8.1
stl_logging.h
Go to the documentation of this file.
1 // Copyright 2010-2018 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.
33 template <class First, class Second>
34 std::ostream& operator<<(std::ostream& out, const std::pair<First, Second>& p);
35 
36 namespace google {
37 
38 template <class Iter>
39 void 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 
51 OUTPUT_TWO_ARG_CONTAINER(std::vector)
52 OUTPUT_TWO_ARG_CONTAINER(std::deque)
53 OUTPUT_TWO_ARG_CONTAINER(std::list)
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 
66 OUTPUT_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 
79 OUTPUT_FOUR_ARG_CONTAINER(std::multimap)
80 OUTPUT_FOUR_ARG_CONTAINER(absl::flat_hash_set)
81 OUTPUT_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 
93 OUTPUT_FIVE_ARG_CONTAINER(absl::flat_hash_map)
94 OUTPUT_FIVE_ARG_CONTAINER(absl::node_hash_map)
95 
96 #undef OUTPUT_FIVE_ARG_CONTAINER
97 
98 template <class First, class Second>
99 inline std::ostream& operator<<(std::ostream& out,
100  const std::pair<First, Second>& p) {
101  out << '(' << p.first << ", " << p.second << ')';
102  return out;
103 }
104 
105 namespace google {
106 
107 template <class Iter>
108 inline 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.
145 namespace std {
146 using ::operator<<;
147 }
148 
149 #endif // OR_TOOLS_BASE_STL_LOGGING_H_
OUTPUT_THREE_ARG_CONTAINER
#define OUTPUT_THREE_ARG_CONTAINER(Sequence)
Definition: stl_logging.h:57
OUTPUT_TWO_ARG_CONTAINER
#define OUTPUT_TWO_ARG_CONTAINER(Sequence)
Definition: stl_logging.h:43
google::PrintSequence
void PrintSequence(std::ostream &out, Iter begin, Iter end)
Definition: stl_logging.h:108
OUTPUT_FOUR_ARG_CONTAINER
#define OUTPUT_FOUR_ARG_CONTAINER(Sequence)
Definition: stl_logging.h:70
OUTPUT_FIVE_ARG_CONTAINER
#define OUTPUT_FIVE_ARG_CONTAINER(Sequence)
Definition: stl_logging.h:85
operator<<
std::ostream & operator<<(std::ostream &out, const std::pair< First, Second > &p)
Definition: stl_logging.h:99
google
Definition: log_severity.h:24