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
25namespace 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.
28template <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.
34template <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>
47namespace 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.
51template <typename T>
52struct 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.
64template <typename T> struct ConvertibleTo { operator T(); };
65template <typename T>
66struct 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.
73template <typename T>
74struct 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

source code of third-party/unittest/googletest/include/gtest/internal/custom/raw-ostream.h