106f32e7eSjoerg //===-- raw-ostream.h - Support for printing using raw_ostream --*- C++ -*-===//
206f32e7eSjoerg //
306f32e7eSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406f32e7eSjoerg // See https://llvm.org/LICENSE.txt for license information.
506f32e7eSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606f32e7eSjoerg //
706f32e7eSjoerg //===----------------------------------------------------------------------===//
806f32e7eSjoerg // This file is not part of gtest, but extends it to support LLVM libraries.
906f32e7eSjoerg // This is not a public API for testing - it's a detail of LLVM's gtest.
1006f32e7eSjoerg //
1106f32e7eSjoerg // gtest allows providing printers for custom types by defining operator<<.
1206f32e7eSjoerg // In LLVM, operator<< usually takes llvm:raw_ostream& instead of std::ostream&.
1306f32e7eSjoerg //
1406f32e7eSjoerg // This file defines a template printable(V), which returns a version of V that
1506f32e7eSjoerg // can be streamed into a std::ostream.
1606f32e7eSjoerg //
1706f32e7eSjoerg // This interface is chosen so that in the default case (printable(V) is V),
1806f32e7eSjoerg // the main gtest code calls operator<<(OS, V) itself. gtest-printers carefully
1906f32e7eSjoerg // controls the lookup to enable fallback printing (see testing::internal2).
2006f32e7eSjoerg //===----------------------------------------------------------------------===//
2106f32e7eSjoerg 
2206f32e7eSjoerg #ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_RAW_OSTREAM_H_
2306f32e7eSjoerg #define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_RAW_OSTREAM_H_
2406f32e7eSjoerg 
2506f32e7eSjoerg namespace llvm_gtest {
2606f32e7eSjoerg // StreamSwitch is a trait that tells us how to stream a T into a std::ostream.
2706f32e7eSjoerg // By default, we just stream the T directly. We'll specialize this later.
2806f32e7eSjoerg template <typename T, typename Enable = void> struct StreamSwitch {
printableStreamSwitch2906f32e7eSjoerg   static const T& printable(const T& V) { return V; }
3006f32e7eSjoerg };
3106f32e7eSjoerg 
3206f32e7eSjoerg // printable() returns a version of its argument that can be streamed into a
3306f32e7eSjoerg // std::ostream. This may be the argument itself, or some other representation.
decltype(auto)34*da58b97aSjoerg template <typename T> decltype(auto) printable(const T &V) {
3506f32e7eSjoerg   // We delegate to the trait, to allow partial specialization.
3606f32e7eSjoerg   return StreamSwitch<T>::printable(V);
3706f32e7eSjoerg }
3806f32e7eSjoerg } // namespace llvm_gtest
3906f32e7eSjoerg 
4006f32e7eSjoerg // If raw_ostream support is enabled, we specialize for types with operator<<
4106f32e7eSjoerg // that takes a raw_ostream.
4206f32e7eSjoerg #if !GTEST_NO_LLVM_SUPPORT
4306f32e7eSjoerg #include "llvm/ADT/Optional.h"
4406f32e7eSjoerg #include "llvm/Support/raw_os_ostream.h"
4506f32e7eSjoerg #include "llvm/Support/raw_ostream.h"
4606f32e7eSjoerg #include <ostream>
4706f32e7eSjoerg namespace llvm_gtest {
4806f32e7eSjoerg 
4906f32e7eSjoerg // The printable() of a raw_ostream-enabled type T is a RawStreamProxy<T>.
5006f32e7eSjoerg // It uses raw_os_ostream to write the wrapped value to a std::ostream.
5106f32e7eSjoerg template <typename T>
5206f32e7eSjoerg struct RawStreamProxy {
5306f32e7eSjoerg   const T& V;
5406f32e7eSjoerg   friend std::ostream &operator<<(std::ostream &S, const RawStreamProxy<T> &V) {
5506f32e7eSjoerg     llvm::raw_os_ostream OS(S);
5606f32e7eSjoerg     OS << V.V;
5706f32e7eSjoerg     return S;
5806f32e7eSjoerg   }
5906f32e7eSjoerg };
6006f32e7eSjoerg 
6106f32e7eSjoerg // We enable raw_ostream treatment if `(raw_ostream&) << (const T&)` is valid.
6206f32e7eSjoerg // We don't want implicit conversions on the RHS (e.g. to bool!), so "consume"
6306f32e7eSjoerg // the possible conversion by passing something convertible to const T& instead.
6406f32e7eSjoerg template <typename T> struct ConvertibleTo { operator T(); };
6506f32e7eSjoerg template <typename T>
6606f32e7eSjoerg struct StreamSwitch<T, decltype((void)(std::declval<llvm::raw_ostream &>()
6706f32e7eSjoerg                                        << ConvertibleTo<const T &>()))> {
6806f32e7eSjoerg   static const RawStreamProxy<T> printable(const T &V) { return {V}; }
6906f32e7eSjoerg };
7006f32e7eSjoerg 
7106f32e7eSjoerg // llvm::Optional has a template operator<<, which means it will not accept any
7206f32e7eSjoerg // implicit conversions, so we need to special-case it here.
7306f32e7eSjoerg template <typename T>
7406f32e7eSjoerg struct StreamSwitch<llvm::Optional<T>,
7506f32e7eSjoerg                     decltype((void)(std::declval<llvm::raw_ostream &>()
7606f32e7eSjoerg                                     << std::declval<llvm::Optional<T>>()))> {
7706f32e7eSjoerg   static const RawStreamProxy<llvm::Optional<T>>
7806f32e7eSjoerg   printable(const llvm::Optional<T> &V) {
7906f32e7eSjoerg     return {V};
8006f32e7eSjoerg   }
8106f32e7eSjoerg };
8206f32e7eSjoerg } // namespace llvm_gtest
8306f32e7eSjoerg #endif  // !GTEST_NO_LLVM_SUPPORT
8406f32e7eSjoerg 
8506f32e7eSjoerg #endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_RAW_OSTREAM_H_
86