• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-- raw-ostream.h - Support for printing using raw_ostream --*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 // This file is not part of gtest, but extends it to support LLVM libraries.
9 // This is not a public API for testing - it's a detail of LLVM's gtest.
10 //
11 // gtest allows providing printers for custom types by defining operator<<.
12 // In LLVM, operator<< usually takes llvm:raw_ostream& instead of std::ostream&.
13 //
14 // This file defines a template printable(V), which returns a version of V that
15 // can be streamed into a std::ostream.
16 //
17 // This interface is chosen so that in the default case (printable(V) is V),
18 // the main gtest code calls operator<<(OS, V) itself. gtest-printers carefully
19 // controls the lookup to enable fallback printing (see testing::internal2).
20 //===----------------------------------------------------------------------===//
21 
22 #ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_RAW_OSTREAM_H_
23 #define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_RAW_OSTREAM_H_
24 
25 namespace llvm_gtest {
26 // StreamSwitch is a trait that tells us how to stream a T into a std::ostream.
27 // By default, we just stream the T directly. We'll specialize this later.
28 template <typename T, typename Enable = void> struct StreamSwitch {
printableStreamSwitch29   static const T& printable(const T& V) { return V; }
30 };
31 
32 // printable() returns a version of its argument that can be streamed into a
33 // std::ostream. This may be the argument itself, or some other representation.
decltype(auto)34 template <typename T> decltype(auto) printable(const T &V) {
35   // We delegate to the trait, to allow partial specialization.
36   return StreamSwitch<T>::printable(V);
37 }
38 } // namespace llvm_gtest
39 
40 // If raw_ostream support is enabled, we specialize for types with operator<<
41 // that takes a raw_ostream.
42 #if !GTEST_NO_LLVM_SUPPORT
43 #include "llvm/ADT/Optional.h"
44 #include "llvm/Support/raw_os_ostream.h"
45 #include "llvm/Support/raw_ostream.h"
46 #include <ostream>
47 namespace llvm_gtest {
48 
49 // The printable() of a raw_ostream-enabled type T is a RawStreamProxy<T>.
50 // It uses raw_os_ostream to write the wrapped value to a std::ostream.
51 template <typename T>
52 struct RawStreamProxy {
53   const T& V;
54   friend std::ostream &operator<<(std::ostream &S, const RawStreamProxy<T> &V) {
55     llvm::raw_os_ostream OS(S);
56     OS << V.V;
57     return S;
58   }
59 };
60 
61 // We enable raw_ostream treatment if `(raw_ostream&) << (const T&)` is valid.
62 // We don't want implicit conversions on the RHS (e.g. to bool!), so "consume"
63 // the possible conversion by passing something convertible to const T& instead.
64 template <typename T> struct ConvertibleTo { operator T(); };
65 template <typename T>
66 struct StreamSwitch<T, decltype((void)(std::declval<llvm::raw_ostream &>()
67                                        << ConvertibleTo<const T &>()))> {
68   static const RawStreamProxy<T> printable(const T &V) { return {V}; }
69 };
70 
71 // llvm::Optional has a template operator<<, which means it will not accept any
72 // implicit conversions, so we need to special-case it here.
73 template <typename T>
74 struct StreamSwitch<llvm::Optional<T>,
75                     decltype((void)(std::declval<llvm::raw_ostream &>()
76                                     << std::declval<llvm::Optional<T>>()))> {
77   static const RawStreamProxy<llvm::Optional<T>>
78   printable(const llvm::Optional<T> &V) {
79     return {V};
80   }
81 };
82 } // namespace llvm_gtest
83 #endif  // !GTEST_NO_LLVM_SUPPORT
84 
85 #endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_RAW_OSTREAM_H_
86