From d5acc83a3ac3db85ca30b9e73b1bdb112f313d1b Mon Sep 17 00:00:00 2001 From: Christian Sigg Date: Mon, 9 Dec 2019 13:32:53 -0800 Subject: [PATCH] Implement LWG#1203 for raw_ostream. Implement LWG#1203 (https://cplusplus.github.io/LWG/issue1203) for raw_ostream like libc++ does for std::basic_ostream<...>. Add a operator<< overload that takes an rvalue reference of a typed derived from raw_ostream, streams the value to it and returns the stream of the same type as the argument. This allows free operator<< to work with rvalue reference raw_ostreams: raw_ostream& operator<<(raw_ostream&, const SomeType& Value); raw_os_ostream(std::cout) << SomeType(); It also allows using the derived type like: auto Foo = (raw_string_ostream(buffer) << "foo").str(); Author: Christian Sigg Differential Revision: https://reviews.llvm.org/D70686 --- llvm/include/llvm/Support/raw_ostream.h | 12 ++++++++++++ llvm/unittests/Support/raw_ostream_test.cpp | 13 +++++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/Support/raw_ostream.h b/llvm/include/llvm/Support/raw_ostream.h index 705f179..c8770c3 100644 --- a/llvm/include/llvm/Support/raw_ostream.h +++ b/llvm/include/llvm/Support/raw_ostream.h @@ -21,6 +21,7 @@ #include #include #include +#include namespace llvm { @@ -354,6 +355,17 @@ private: virtual void anchor(); }; +/// Call the appropriate insertion operator, given an rvalue reference to a +/// raw_ostream object and return a stream of the same type as the argument. +template +typename std::enable_if::value && + std::is_base_of::value, + OStream &&>::type +operator<<(OStream &&OS, const T &Value) { + OS << Value; + return std::move(OS); +} + /// An abstract base class for streams implementations that also support a /// pwrite operation. This is useful for code that can mostly stream out data, /// but needs to patch in a header that needs to know the output size. diff --git a/llvm/unittests/Support/raw_ostream_test.cpp b/llvm/unittests/Support/raw_ostream_test.cpp index 497d313..0e56464 100644 --- a/llvm/unittests/Support/raw_ostream_test.cpp +++ b/llvm/unittests/Support/raw_ostream_test.cpp @@ -18,8 +18,7 @@ namespace { template std::string printToString(const T &Value) { std::string res; - llvm::raw_string_ostream(res) << Value; - return res; + return (llvm::raw_string_ostream(res) << Value).str(); } /// printToString - Print the given value to a stream which only has \arg @@ -47,6 +46,10 @@ template std::string printToStringUnbuffered(const T &Value) { return res; } +struct X {}; + +raw_ostream &operator<<(raw_ostream &OS, const X &) { return OS << 'X'; } + TEST(raw_ostreamTest, Types_Buffered) { // Char EXPECT_EQ("c", printToString('c')); @@ -76,6 +79,9 @@ TEST(raw_ostreamTest, Types_Buffered) { // Min and max. EXPECT_EQ("18446744073709551615", printToString(UINT64_MAX)); EXPECT_EQ("-9223372036854775808", printToString(INT64_MIN)); + + // X, checking free operator<<(). + EXPECT_EQ("X", printToString(X{})); } TEST(raw_ostreamTest, Types_Unbuffered) { @@ -107,6 +113,9 @@ TEST(raw_ostreamTest, Types_Unbuffered) { // Min and max. EXPECT_EQ("18446744073709551615", printToStringUnbuffered(UINT64_MAX)); EXPECT_EQ("-9223372036854775808", printToStringUnbuffered(INT64_MIN)); + + // X, checking free operator<<(). + EXPECT_EQ("X", printToString(X{})); } TEST(raw_ostreamTest, BufferEdge) { -- 2.7.4