Skip to content

Commit d5acc83

Browse files
chsiggArtem-B
authored andcommitted
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 <[email protected]> Differential Revision: https://reviews.llvm.org/D70686
1 parent 9ef451d commit d5acc83

File tree

2 files changed

+23
-2
lines changed

2 files changed

+23
-2
lines changed

llvm/include/llvm/Support/raw_ostream.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <cstring>
2222
#include <string>
2323
#include <system_error>
24+
#include <type_traits>
2425

2526
namespace llvm {
2627

@@ -354,6 +355,17 @@ class raw_ostream {
354355
virtual void anchor();
355356
};
356357

358+
/// Call the appropriate insertion operator, given an rvalue reference to a
359+
/// raw_ostream object and return a stream of the same type as the argument.
360+
template <typename OStream, typename T>
361+
typename std::enable_if<!std::is_reference<OStream>::value &&
362+
std::is_base_of<raw_ostream, OStream>::value,
363+
OStream &&>::type
364+
operator<<(OStream &&OS, const T &Value) {
365+
OS << Value;
366+
return std::move(OS);
367+
}
368+
357369
/// An abstract base class for streams implementations that also support a
358370
/// pwrite operation. This is useful for code that can mostly stream out data,
359371
/// but needs to patch in a header that needs to know the output size.

llvm/unittests/Support/raw_ostream_test.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ namespace {
1818

1919
template<typename T> std::string printToString(const T &Value) {
2020
std::string res;
21-
llvm::raw_string_ostream(res) << Value;
22-
return res;
21+
return (llvm::raw_string_ostream(res) << Value).str();
2322
}
2423

2524
/// printToString - Print the given value to a stream which only has \arg
@@ -47,6 +46,10 @@ template<typename T> std::string printToStringUnbuffered(const T &Value) {
4746
return res;
4847
}
4948

49+
struct X {};
50+
51+
raw_ostream &operator<<(raw_ostream &OS, const X &) { return OS << 'X'; }
52+
5053
TEST(raw_ostreamTest, Types_Buffered) {
5154
// Char
5255
EXPECT_EQ("c", printToString('c'));
@@ -76,6 +79,9 @@ TEST(raw_ostreamTest, Types_Buffered) {
7679
// Min and max.
7780
EXPECT_EQ("18446744073709551615", printToString(UINT64_MAX));
7881
EXPECT_EQ("-9223372036854775808", printToString(INT64_MIN));
82+
83+
// X, checking free operator<<().
84+
EXPECT_EQ("X", printToString(X{}));
7985
}
8086

8187
TEST(raw_ostreamTest, Types_Unbuffered) {
@@ -107,6 +113,9 @@ TEST(raw_ostreamTest, Types_Unbuffered) {
107113
// Min and max.
108114
EXPECT_EQ("18446744073709551615", printToStringUnbuffered(UINT64_MAX));
109115
EXPECT_EQ("-9223372036854775808", printToStringUnbuffered(INT64_MIN));
116+
117+
// X, checking free operator<<().
118+
EXPECT_EQ("X", printToString(X{}));
110119
}
111120

112121
TEST(raw_ostreamTest, BufferEdge) {

0 commit comments

Comments
 (0)