blob: 5cd5f12e6a8a392fde0a0898a99d21c3c38ae95c [file] [log] [blame]
shiqiane35fdd92008-12-10 05:08:54 +00001// Copyright 2007, 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// Author: wan@google.com (Zhanyong Wan)
31
32// Google Mock - a framework for writing C++ mock classes.
33//
34// This file implements a universal value printer that can print a
35// value of any type T:
36//
37// void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr);
38//
39// It uses the << operator when possible, and prints the bytes in the
40// object otherwise. A user can override its behavior for a class
41// type Foo by defining either operator<<(::std::ostream&, const Foo&)
42// or void PrintTo(const Foo&, ::std::ostream*) in the namespace that
43// defines Foo. If both are defined, PrintTo() takes precedence.
44// When T is a reference type, the address of the value is also
45// printed.
46//
zhanyong.wance198ff2009-02-12 01:34:27 +000047// We also provide some convenient wrappers:
shiqiane35fdd92008-12-10 05:08:54 +000048//
zhanyong.wance198ff2009-02-12 01:34:27 +000049// // Prints to a string.
shiqiane35fdd92008-12-10 05:08:54 +000050// string ::testing::internal::UniversalPrinter<T>::PrintAsString(value);
zhanyong.wance198ff2009-02-12 01:34:27 +000051// // Prints a value using its inferred type.
52// void ::testing::internal::UniversalPrint(const T& value, ostream*);
shiqiane35fdd92008-12-10 05:08:54 +000053
54#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_PRINTERS_H_
55#define GMOCK_INCLUDE_GMOCK_GMOCK_PRINTERS_H_
56
57#include <ostream> // NOLINT
58#include <string>
59#include <utility>
60
61#include <gmock/internal/gmock-internal-utils.h>
62#include <gmock/internal/gmock-port.h>
63#include <gtest/gtest.h>
64
65// Makes sure there is at least one << operator declared in the global
66// namespace. This has no implementation and won't be called
67// anywhere. We just need the declaration such that we can say "using
68// ::operator <<;" in the definition of PrintTo() below.
69void operator<<(::testing::internal::Unused, int);
70
71namespace testing {
72
73// Definitions in the 'internal' and 'internal2' name spaces are
74// subject to change without notice. DO NOT USE THEM IN USER CODE!
75namespace internal2 {
76
77// Prints the given number of bytes in the given object to the given
78// ostream.
79void PrintBytesInObjectTo(const unsigned char* obj_bytes,
80 size_t count,
81 ::std::ostream* os);
82
83// TypeWithoutFormatter<T, kIsProto>::PrintValue(value, os) is called
84// by the universal printer to print a value of type T when neither
85// operator<< nor PrintTo() is defined for type T. When T is
86// ProtocolMessage, proto2::Message, or a subclass of those, kIsProto
87// will be true and the short debug string of the protocol message
88// value will be printed; otherwise kIsProto will be false and the
89// bytes in the value will be printed.
90template <typename T, bool kIsProto>
91class TypeWithoutFormatter {
92 public:
93 static void PrintValue(const T& value, ::std::ostream* os) {
94 PrintBytesInObjectTo(reinterpret_cast<const unsigned char*>(&value),
95 sizeof(value), os);
96 }
97};
98template <typename T>
99class TypeWithoutFormatter<T, true> {
100 public:
101 static void PrintValue(const T& value, ::std::ostream* os) {
102 // Both ProtocolMessage and proto2::Message have the
103 // ShortDebugString() method, so the same implementation works for
104 // both.
105 ::std::operator<<(*os, "<" + value.ShortDebugString() + ">");
106 }
107};
108
109// Prints the given value to the given ostream. If the value is a
110// protocol message, its short debug string is printed; otherwise the
111// bytes in the value are printed. This is what
112// UniversalPrinter<T>::Print() does when it knows nothing about type
113// T and T has no << operator.
114//
115// A user can override this behavior for a class type Foo by defining
116// a << operator in the namespace where Foo is defined.
117//
118// We put this operator in namespace 'internal2' instead of 'internal'
119// to simplify the implementation, as much code in 'internal' needs to
120// use << in STL, which would conflict with our own << were it defined
121// in 'internal'.
zhanyong.wan2f0849f2009-02-11 18:06:37 +0000122//
123// Note that this operator<< takes a generic std::basic_ostream<Char,
124// CharTraits> type instead of the more restricted std::ostream. If
125// we define it to take an std::ostream instead, we'll get an
126// "ambiguous overloads" compiler error when trying to print a type
127// Foo that supports streaming to std::basic_ostream<Char,
128// CharTraits>, as the compiler cannot tell whether
129// operator<<(std::ostream&, const T&) or
130// operator<<(std::basic_stream<Char, CharTraits>, const Foo&) is more
131// specific.
132template <typename Char, typename CharTraits, typename T>
133::std::basic_ostream<Char, CharTraits>& operator<<(
134 ::std::basic_ostream<Char, CharTraits>& os, const T& x) {
shiqiane35fdd92008-12-10 05:08:54 +0000135 TypeWithoutFormatter<T, ::testing::internal::IsAProtocolMessage<T>::value>::
136 PrintValue(x, &os);
137 return os;
138}
139
140} // namespace internal2
141
142namespace internal {
143
144// UniversalPrinter<T>::Print(value, ostream_ptr) prints the given
145// value to the given ostream. The caller must ensure that
146// 'ostream_ptr' is not NULL, or the behavior is undefined.
147//
148// We define UniversalPrinter as a class template (as opposed to a
149// function template), as we need to partially specialize it for
150// reference types, which cannot be done with function templates.
151template <typename T>
152class UniversalPrinter;
153
154// Used to print an STL-style container when the user doesn't define
155// a PrintTo() for it.
156template <typename C>
157void DefaultPrintTo(IsContainer, const C& container, ::std::ostream* os) {
158 const size_t kMaxCount = 32; // The maximum number of elements to print.
159 *os << '{';
160 size_t count = 0;
161 for (typename C::const_iterator it = container.begin();
162 it != container.end(); ++it, ++count) {
163 if (count > 0) {
164 *os << ',';
165 if (count == kMaxCount) { // Enough has been printed.
166 *os << " ...";
167 break;
168 }
169 }
170 *os << ' ';
171 PrintTo(*it, os);
172 }
173
174 if (count > 0) {
175 *os << ' ';
176 }
177 *os << '}';
178}
179
180// Used to print a value when the user doesn't define PrintTo() for it.
181template <typename T>
182void DefaultPrintTo(IsNotContainer, const T& value, ::std::ostream* os) {
183 // If T has its << operator defined in the global namespace, which
184 // is not recommended but sometimes unavoidable (as in
185 // util/gtl/stl_logging-inl.h), the following statement makes it
186 // visible in this function.
187 //
188 // Without the statement, << in the global namespace would be hidden
189 // by the one in ::testing::internal2, due to the next using
190 // statement.
191 using ::operator <<;
192
193 // When T doesn't come with a << operator, we want to fall back to
194 // the one defined in ::testing::internal2, which prints the bytes in
195 // the value.
196 using ::testing::internal2::operator <<;
197
198 // Thanks to Koenig look-up, if type T has its own << operator
199 // defined in its namespace, which is the recommended way, that
200 // operator will be visible here. Since it is more specific than
201 // the generic one, it will be picked by the compiler in the
202 // following statement - exactly what we want.
203 *os << value;
204}
205
206// Prints the given value using the << operator if it has one;
207// otherwise prints the bytes in it. This is what
208// UniversalPrinter<T>::Print() does when PrintTo() is not specialized
209// or overloaded for type T.
210//
211// A user can override this behavior for a class type Foo by defining
212// an overload of PrintTo() in the namespace where Foo is defined. We
213// give the user this option as sometimes defining a << operator for
214// Foo is not desirable (e.g. the coding style may prevent doing it,
215// or there is already a << operator but it doesn't do what the user
216// wants).
217template <typename T>
218void PrintTo(const T& value, ::std::ostream* os) {
219 // DefaultPrintTo() is overloaded. The type of its first argument
220 // determines which version will be picked. If T is an STL-style
221 // container, the version for container will be called. Otherwise
222 // the generic version will be called.
223 //
224 // Note that we check for container types here, prior to we check
225 // for protocol message types in our operator<<. The rationale is:
226 //
227 // For protocol messages, we want to give people a chance to
228 // override Google Mock's format by defining a PrintTo() or
229 // operator<<. For STL containers, we believe the Google Mock's
230 // format is superior to what util/gtl/stl-logging.h offers.
231 // Therefore we don't want it to be accidentally overridden by the
232 // latter (even if the user includes stl-logging.h through other
233 // headers indirectly, Google Mock's format will still be used).
234 DefaultPrintTo(IsContainerTest<T>(0), value, os);
235}
236
237// The following list of PrintTo() overloads tells
238// UniversalPrinter<T>::Print() how to print standard types (built-in
239// types, strings, plain arrays, and pointers).
240
241// Overloads for various char types.
242void PrintCharTo(char c, int char_code, ::std::ostream* os);
243inline void PrintTo(unsigned char c, ::std::ostream* os) {
244 PrintCharTo(c, c, os);
245}
246inline void PrintTo(signed char c, ::std::ostream* os) {
247 PrintCharTo(c, c, os);
248}
249inline void PrintTo(char c, ::std::ostream* os) {
250 // When printing a plain char, we always treat it as unsigned. This
251 // way, the output won't be affected by whether the compiler thinks
252 // char is signed or not.
253 PrintTo(static_cast<unsigned char>(c), os);
254}
255
256// Overloads for other simple built-in types.
257inline void PrintTo(bool x, ::std::ostream* os) {
258 *os << (x ? "true" : "false");
259}
260
261// Overload for wchar_t type.
262// Prints a wchar_t as a symbol if it is printable or as its internal
263// code otherwise and also as its decimal code (except for L'\0').
264// The L'\0' char is printed as "L'\\0'". The decimal code is printed
265// as signed integer when wchar_t is implemented by the compiler
266// as a signed type and is printed as an unsigned integer when wchar_t
267// is implemented as an unsigned type.
268void PrintTo(wchar_t wc, ::std::ostream* os);
269
270// Overloads for C strings.
271void PrintTo(const char* s, ::std::ostream* os);
272inline void PrintTo(char* s, ::std::ostream* os) {
273 PrintTo(implicit_cast<const char*>(s), os);
274}
275
276// MSVC compiler can be configured to define whar_t as a typedef
277// of unsigned short. Defining an overload for const wchar_t* in that case
278// would cause pointers to unsigned shorts be printed as wide strings,
279// possibly accessing more memory than intended and causing invalid
280// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when
281// wchar_t is implemented as a native type.
282#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
283// Overloads for wide C strings
284void PrintTo(const wchar_t* s, ::std::ostream* os);
285inline void PrintTo(wchar_t* s, ::std::ostream* os) {
286 PrintTo(implicit_cast<const wchar_t*>(s), os);
287}
288#endif
289
290// Overload for pointers that are neither char pointers nor member
291// pointers. (A member variable pointer or member function pointer
292// doesn't really points to a location in the address space. Their
293// representation is implementation-defined. Therefore they will be
294// printed as raw bytes.)
295template <typename T>
296void PrintTo(T* p, ::std::ostream* os) {
297 if (p == NULL) {
298 *os << "NULL";
299 } else {
300 // We cannot use implicit_cast or static_cast here, as they don't
301 // work when p is a function pointer.
302 *os << reinterpret_cast<const void*>(p);
303 }
304}
305
306// Overload for C arrays. Multi-dimensional arrays are printed
307// properly.
308
309// Prints the given number of elements in an array, without printing
310// the curly braces.
311template <typename T>
312void PrintRawArrayTo(const T a[], size_t count, ::std::ostream* os) {
313 UniversalPrinter<T>::Print(a[0], os);
314 for (size_t i = 1; i != count; i++) {
315 *os << ", ";
316 UniversalPrinter<T>::Print(a[i], os);
317 }
318}
319
320// Overloads for ::string and ::std::string.
321#if GTEST_HAS_GLOBAL_STRING
322void PrintStringTo(const ::string&s, ::std::ostream* os);
323inline void PrintTo(const ::string& s, ::std::ostream* os) {
324 PrintStringTo(s, os);
325}
326#endif // GTEST_HAS_GLOBAL_STRING
327
328#if GTEST_HAS_STD_STRING
329void PrintStringTo(const ::std::string&s, ::std::ostream* os);
330inline void PrintTo(const ::std::string& s, ::std::ostream* os) {
331 PrintStringTo(s, os);
332}
333#endif // GTEST_HAS_STD_STRING
334
335// Overloads for ::wstring and ::std::wstring.
336#if GTEST_HAS_GLOBAL_WSTRING
337void PrintWideStringTo(const ::wstring&s, ::std::ostream* os);
338inline void PrintTo(const ::wstring& s, ::std::ostream* os) {
339 PrintWideStringTo(s, os);
340}
341#endif // GTEST_HAS_GLOBAL_WSTRING
342
343#if GTEST_HAS_STD_WSTRING
344void PrintWideStringTo(const ::std::wstring&s, ::std::ostream* os);
345inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) {
346 PrintWideStringTo(s, os);
347}
348#endif // GTEST_HAS_STD_WSTRING
349
350// Overload for ::std::tr1::tuple. Needed for printing function
351// arguments, which are packed as tuples.
352
353// This helper template allows PrintTo() for tuples to be defined by
354// induction on the number of tuple fields. The idea is that
355// TuplePrefixPrinter<N>::PrintPrefixTo(t, os) prints the first N
356// fields in tuple t, and can be defined in terms of
357// TuplePrefixPrinter<N - 1>.
358template <size_t N>
359struct TuplePrefixPrinter {
360 template <typename Tuple>
361 static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) {
362 TuplePrefixPrinter<N - 1>::PrintPrefixTo(t, os);
363 *os << ", ";
364 UniversalPrinter<typename ::std::tr1::tuple_element<N - 1, Tuple>::type>
365 ::Print(::std::tr1::get<N - 1>(t), os);
366 }
367};
368template <>
369struct TuplePrefixPrinter<0> {
370 template <typename Tuple>
371 static void PrintPrefixTo(const Tuple&, ::std::ostream*) {}
372};
373template <>
374struct TuplePrefixPrinter<1> {
375 template <typename Tuple>
376 static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) {
377 UniversalPrinter<typename ::std::tr1::tuple_element<0, Tuple>::type>::
378 Print(::std::tr1::get<0>(t), os);
379 }
380};
381
shiqianc97f2f52008-12-11 17:22:59 +0000382// Helper function for printing a tuple. T must be instantiated with
383// a tuple type.
384template <typename T>
385void PrintTupleTo(const T& t, ::std::ostream* os) {
386 *os << "(";
387 TuplePrefixPrinter< ::std::tr1::tuple_size<T>::value>::
388 PrintPrefixTo(t, os);
389 *os << ")";
390}
391
392// Overloaded PrintTo() for tuples of various arities. We support
393// tuples of up-to 10 fields. The following implementation works
394// regardless of whether tr1::tuple is implemented using the
395// non-standard variadic template feature or not.
396
397inline void PrintTo(const ::std::tr1::tuple<>& t, ::std::ostream* os) {
398 PrintTupleTo(t, os);
399}
400
401template <typename T1>
402void PrintTo(const ::std::tr1::tuple<T1>& t, ::std::ostream* os) {
403 PrintTupleTo(t, os);
404}
405
406template <typename T1, typename T2>
407void PrintTo(const ::std::tr1::tuple<T1, T2>& t, ::std::ostream* os) {
408 PrintTupleTo(t, os);
409}
410
411template <typename T1, typename T2, typename T3>
412void PrintTo(const ::std::tr1::tuple<T1, T2, T3>& t, ::std::ostream* os) {
413 PrintTupleTo(t, os);
414}
415
416template <typename T1, typename T2, typename T3, typename T4>
417void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4>& t, ::std::ostream* os) {
418 PrintTupleTo(t, os);
419}
420
421template <typename T1, typename T2, typename T3, typename T4, typename T5>
422void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5>& t,
423 ::std::ostream* os) {
424 PrintTupleTo(t, os);
425}
426
427template <typename T1, typename T2, typename T3, typename T4, typename T5,
428 typename T6>
429void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6>& t,
430 ::std::ostream* os) {
431 PrintTupleTo(t, os);
432}
433
434template <typename T1, typename T2, typename T3, typename T4, typename T5,
435 typename T6, typename T7>
436void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7>& t,
437 ::std::ostream* os) {
438 PrintTupleTo(t, os);
439}
440
441template <typename T1, typename T2, typename T3, typename T4, typename T5,
442 typename T6, typename T7, typename T8>
443void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8>& t,
444 ::std::ostream* os) {
445 PrintTupleTo(t, os);
446}
447
448template <typename T1, typename T2, typename T3, typename T4, typename T5,
449 typename T6, typename T7, typename T8, typename T9>
450void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9>& t,
451 ::std::ostream* os) {
452 PrintTupleTo(t, os);
453}
454
shiqiane35fdd92008-12-10 05:08:54 +0000455template <typename T1, typename T2, typename T3, typename T4, typename T5,
456 typename T6, typename T7, typename T8, typename T9, typename T10>
457void PrintTo(
458 const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>& t,
459 ::std::ostream* os) {
shiqianc97f2f52008-12-11 17:22:59 +0000460 PrintTupleTo(t, os);
shiqiane35fdd92008-12-10 05:08:54 +0000461}
462
463// Overload for std::pair.
464template <typename T1, typename T2>
465void PrintTo(const ::std::pair<T1, T2>& value, ::std::ostream* os) {
466 *os << '(';
467 UniversalPrinter<T1>::Print(value.first, os);
468 *os << ", ";
469 UniversalPrinter<T2>::Print(value.second, os);
470 *os << ')';
471}
472
473// Implements printing a non-reference type T by letting the compiler
474// pick the right overload of PrintTo() for T.
475template <typename T>
476class UniversalPrinter {
477 public:
478 // MSVC warns about adding const to a function type, so we want to
479 // disable the warning.
480#ifdef _MSC_VER
481#pragma warning(push) // Saves the current warning state.
482#pragma warning(disable:4180) // Temporarily disables warning 4180.
483#endif // _MSC_VER
484
485 // Note: we deliberately don't call this PrintTo(), as that name
486 // conflicts with ::testing::internal::PrintTo in the body of the
487 // function.
488 static void Print(const T& value, ::std::ostream* os) {
489 // By default, ::testing::internal::PrintTo() is used for printing
490 // the value.
491 //
492 // Thanks to Koenig look-up, if T is a class and has its own
493 // PrintTo() function defined in its namespace, that function will
494 // be visible here. Since it is more specific than the generic ones
495 // in ::testing::internal, it will be picked by the compiler in the
496 // following statement - exactly what we want.
497 PrintTo(value, os);
498 }
499
500 // A convenient wrapper for Print() that returns the print-out as a
501 // string.
502 static string PrintAsString(const T& value) {
503 ::std::stringstream ss;
504 Print(value, &ss);
505 return ss.str();
506 }
507
508#ifdef _MSC_VER
509#pragma warning(pop) // Restores the warning state.
510#endif // _MSC_VER
511};
512
513// Implements printing an array type T[N].
514template <typename T, size_t N>
515class UniversalPrinter<T[N]> {
516 public:
517 // Prints the given array, omitting some elements when there are too
518 // many.
519 static void Print(const T (&a)[N], ::std::ostream* os) {
520 // Prints a char array as a C string. Note that we compare 'const
521 // T' with 'const char' instead of comparing T with char, in case
522 // that T is already a const type.
523 if (internal::type_equals<const T, const char>::value) {
524 UniversalPrinter<const T*>::Print(a, os);
525 return;
526 }
527
528 if (N == 0) {
529 *os << "{}";
530 } else {
531 *os << "{ ";
532 const size_t kThreshold = 18;
533 const size_t kChunkSize = 8;
534 // If the array has more than kThreshold elements, we'll have to
535 // omit some details by printing only the first and the last
536 // kChunkSize elements.
537 // TODO(wan): let the user control the threshold using a flag.
538 if (N <= kThreshold) {
539 PrintRawArrayTo(a, N, os);
540 } else {
541 PrintRawArrayTo(a, kChunkSize, os);
542 *os << ", ..., ";
543 PrintRawArrayTo(a + N - kChunkSize, kChunkSize, os);
544 }
545 *os << " }";
546 }
547 }
548
549 // A convenient wrapper for Print() that returns the print-out as a
550 // string.
551 static string PrintAsString(const T (&a)[N]) {
552 ::std::stringstream ss;
553 Print(a, &ss);
554 return ss.str();
555 }
556};
557
558// Implements printing a reference type T&.
559template <typename T>
560class UniversalPrinter<T&> {
561 public:
562 // MSVC warns about adding const to a function type, so we want to
563 // disable the warning.
564#ifdef _MSC_VER
565#pragma warning(push) // Saves the current warning state.
566#pragma warning(disable:4180) // Temporarily disables warning 4180.
567#endif // _MSC_VER
568
569 static void Print(const T& value, ::std::ostream* os) {
570 // Prints the address of the value. We use reinterpret_cast here
571 // as static_cast doesn't compile when T is a function type.
572 *os << "@" << reinterpret_cast<const void*>(&value) << " ";
573
574 // Then prints the value itself.
575 UniversalPrinter<T>::Print(value, os);
576 }
577
578 // A convenient wrapper for Print() that returns the print-out as a
579 // string.
580 static string PrintAsString(const T& value) {
581 ::std::stringstream ss;
582 Print(value, &ss);
583 return ss.str();
584 }
585
586#ifdef _MSC_VER
587#pragma warning(pop) // Restores the warning state.
588#endif // _MSC_VER
589};
590
zhanyong.wance198ff2009-02-12 01:34:27 +0000591// Prints a value using its inferred type. In particular, if the
592// original type of the value is a reference, the *referenced* type
593// (as opposed to the reference type) will be used, as C++ doesn't
594// infer reference types. This is useful when you just want to know
595// what the value is and don't care if it's a reference or not.
596template <typename T>
597void UniversalPrint(const T& value, ::std::ostream* os) {
598 UniversalPrinter<T>::Print(value, os);
599}
600
shiqiane35fdd92008-12-10 05:08:54 +0000601} // namespace internal
602} // namespace testing
603
604#endif // GMOCK_INCLUDE_GMOCK_GMOCK_PRINTERS_H_