Fix glog/stl_logging for clang
[platform/upstream/glog.git] / src / glog / stl_logging.h.in
1 // Copyright (c) 2003, Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
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
13 // distribution.
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.
17 //
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.
29 //
30 // Stream output operators for STL containers; to be used for logging *only*.
31 // Inclusion of this file lets you do:
32 //
33 // list<string> x;
34 // LOG(INFO) << "data: " << x;
35 // vector<int> v1, v2;
36 // CHECK_EQ(v1, v2);
37
38 #ifndef UTIL_GTL_STL_LOGGING_INL_H_
39 #define UTIL_GTL_STL_LOGGING_INL_H_
40
41 #if !@ac_cv_cxx_using_operator@
42 # error We do not support stl_logging for this compiler
43 #endif
44
45 #include <deque>
46 #include <list>
47 #include <map>
48 #include <ostream>
49 #include <set>
50 #include <utility>
51 #include <vector>
52
53 #ifdef __GNUC__
54 # include <ext/hash_set>
55 # include <ext/hash_map>
56 # include <ext/slist>
57 #endif
58
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
61 // properly.
62 template<class First, class Second>
63 std::ostream& operator<<(std::ostream& out, const std::pair<First, Second>& p);
64
65 @ac_google_start_namespace@
66
67 template<class Iter>
68 void PrintSequence(std::ostream& out, Iter begin, Iter end);
69
70 @ac_google_end_namespace@
71
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()); \
77   return out; \
78 }
79
80 OUTPUT_TWO_ARG_CONTAINER(std::vector)
81 OUTPUT_TWO_ARG_CONTAINER(std::deque)
82 OUTPUT_TWO_ARG_CONTAINER(std::list)
83 #ifdef __GNUC__
84 OUTPUT_TWO_ARG_CONTAINER(__gnu_cxx::slist)
85 #endif
86
87 #undef OUTPUT_TWO_ARG_CONTAINER
88
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()); \
94   return out; \
95 }
96
97 OUTPUT_THREE_ARG_CONTAINER(std::set)
98 OUTPUT_THREE_ARG_CONTAINER(std::multiset)
99
100 #undef OUTPUT_THREE_ARG_CONTAINER
101
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()); \
107   return out; \
108 }
109
110 OUTPUT_FOUR_ARG_CONTAINER(std::map)
111 OUTPUT_FOUR_ARG_CONTAINER(std::multimap)
112 #ifdef __GNUC__
113 OUTPUT_FOUR_ARG_CONTAINER(__gnu_cxx::hash_set)
114 OUTPUT_FOUR_ARG_CONTAINER(__gnu_cxx::hash_multiset)
115 #endif
116
117 #undef OUTPUT_FOUR_ARG_CONTAINER
118
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()); \
124   return out; \
125 }
126
127 #ifdef __GNUC__
128 OUTPUT_FIVE_ARG_CONTAINER(__gnu_cxx::hash_map)
129 OUTPUT_FIVE_ARG_CONTAINER(__gnu_cxx::hash_multimap)
130 #endif
131
132 #undef OUTPUT_FIVE_ARG_CONTAINER
133
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 << ')';
138   return out;
139 }
140
141 @ac_google_start_namespace@
142
143 template<class Iter>
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 << ' ';
148     out << *begin;
149   }
150   if (begin != end) {
151     out << " ...";
152   }
153 }
154
155 @ac_google_end_namespace@
156
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.
163 //
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:
167 //   template<class T>
168 //   void MakeCheckOpValueString(strstream* ss, const T& v) {
169 //     (*ss) << v;
170 //   }
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.
174 //
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<<; }
182
183 #endif  // UTIL_GTL_STL_LOGGING_INL_H_