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 { |
29 | 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. |
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/Support/raw_os_ostream.h" |
44 | #include "llvm/Support/raw_ostream.h" |
45 | #include <optional> |
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 | // std::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<std::optional<T>, |
75 | decltype((void)(std::declval<llvm::raw_ostream &>() |
76 | << std::declval<std::optional<T>>()))> { |
77 | static const RawStreamProxy<std::optional<T>> |
78 | printable(const std::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 | |