1 // Copyright (c) 2003, Google Inc.
2 // All rights reserved.
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
14 // * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 // Stream output operators for STL containers; to be used for logging *only*.
31 // Inclusion of this file lets you do:
34 // LOG(INFO) << "data: " << x;
35 // vector<int> v1, v2;
38 #ifndef UTIL_GTL_STL_LOGGING_INL_H_
39 #define UTIL_GTL_STL_LOGGING_INL_H_
41 #if !@ac_cv_cxx_using_operator@
42 # error We do not support stl_logging for this compiler
54 # include <ext/hash_set>
55 # include <ext/hash_map>
59 // Forward declare these two, and define them after all the container streams
60 // operators so that we can recurse from pair -> container -> container -> pair
62 template<class First, class Second>
63 std::ostream& operator<<(std::ostream& out, const std::pair<First, Second>& p);
65 @ac_google_start_namespace@
68 void PrintSequence(std::ostream& out, Iter begin, Iter end);
70 @ac_google_end_namespace@
72 #define OUTPUT_TWO_ARG_CONTAINER(Sequence) \
73 template<class T1, class T2> \
74 inline std::ostream& operator<<(std::ostream& out, \
75 const Sequence<T1, T2>& seq) { \
76 @ac_google_namespace@::PrintSequence(out, seq.begin(), seq.end()); \
80 OUTPUT_TWO_ARG_CONTAINER(std::vector)
81 OUTPUT_TWO_ARG_CONTAINER(std::deque)
82 OUTPUT_TWO_ARG_CONTAINER(std::list)
84 OUTPUT_TWO_ARG_CONTAINER(__gnu_cxx::slist)
87 #undef OUTPUT_TWO_ARG_CONTAINER
89 #define OUTPUT_THREE_ARG_CONTAINER(Sequence) \
90 template<class T1, class T2, class T3> \
91 inline std::ostream& operator<<(std::ostream& out, \
92 const Sequence<T1, T2, T3>& seq) { \
93 @ac_google_namespace@::PrintSequence(out, seq.begin(), seq.end()); \
97 OUTPUT_THREE_ARG_CONTAINER(std::set)
98 OUTPUT_THREE_ARG_CONTAINER(std::multiset)
100 #undef OUTPUT_THREE_ARG_CONTAINER
102 #define OUTPUT_FOUR_ARG_CONTAINER(Sequence) \
103 template<class T1, class T2, class T3, class T4> \
104 inline std::ostream& operator<<(std::ostream& out, \
105 const Sequence<T1, T2, T3, T4>& seq) { \
106 @ac_google_namespace@::PrintSequence(out, seq.begin(), seq.end()); \
110 OUTPUT_FOUR_ARG_CONTAINER(std::map)
111 OUTPUT_FOUR_ARG_CONTAINER(std::multimap)
113 OUTPUT_FOUR_ARG_CONTAINER(__gnu_cxx::hash_set)
114 OUTPUT_FOUR_ARG_CONTAINER(__gnu_cxx::hash_multiset)
117 #undef OUTPUT_FOUR_ARG_CONTAINER
119 #define OUTPUT_FIVE_ARG_CONTAINER(Sequence) \
120 template<class T1, class T2, class T3, class T4, class T5> \
121 inline std::ostream& operator<<(std::ostream& out, \
122 const Sequence<T1, T2, T3, T4, T5>& seq) { \
123 @ac_google_namespace@::PrintSequence(out, seq.begin(), seq.end()); \
128 OUTPUT_FIVE_ARG_CONTAINER(__gnu_cxx::hash_map)
129 OUTPUT_FIVE_ARG_CONTAINER(__gnu_cxx::hash_multimap)
132 #undef OUTPUT_FIVE_ARG_CONTAINER
134 template<class First, class Second>
135 inline std::ostream& operator<<(std::ostream& out,
136 const std::pair<First, Second>& p) {
137 out << '(' << p.first << ", " << p.second << ')';
141 @ac_google_start_namespace@
144 inline void PrintSequence(std::ostream& out, Iter begin, Iter end) {
145 // Output at most 100 elements -- appropriate if used for logging.
146 for (int i = 0; begin != end && i < 100; ++i, ++begin) {
147 if (i > 0) out << ' ';
155 @ac_google_end_namespace@
157 // Note that this is technically undefined behavior! We are adding things into
158 // the std namespace for a reason though -- we are providing new operations on
159 // types which are themselves defined with this namespace. Without this, these
160 // operator overloads cannot be found via ADL. If these definitions are not
161 // found via ADL, they must be #included before they're used, which requires
162 // this header to be included before apparently independent other headers.
164 // For example, base/logging.h defines various template functions to implement
165 // CHECK_EQ(x, y) and stream x and y into the log in the event the check fails.
166 // It does so via the function template MakeCheckOpValueString:
168 // void MakeCheckOpValueString(strstream* ss, const T& v) {
171 // Because 'glog/logging.h' is included before 'glog/stl_logging.h',
172 // subsequent CHECK_EQ(v1, v2) for vector<...> typed variable v1 and v2 can only
173 // find these operator definitions via ADL.
175 // Even this solution has problems -- it may pull unintended operators into the
176 // namespace as well, allowing them to also be found via ADL, and creating code
177 // that only works with a particular order of includes. Long term, we need to
178 // move all of the *definitions* into namespace std, bet we need to ensure no
179 // one references them first. This lets us take that step. We cannot define them
180 // in both because that would create ambiguous overloads when both are found.
181 namespace std { using ::operator<<; }
183 #endif // UTIL_GTL_STL_LOGGING_INL_H_