This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of Open status.

1203. More useful rvalue stream insertion

Section: 27.7.5.5 [ostream.rvalue], 27.7.4.5 [istream.rvalue] Status: Open Submitter: Howard Hinnant Opened: 2009-09-06 Last modified: 2018-06-24

Priority: Not Prioritized

View all other issues in [ostream.rvalue].

View all issues with Open status.

Discussion:

27.7.5.5 [ostream.rvalue] was created to preserve the ability to insert into (and extract from 27.7.4.5 [istream.rvalue]) rvalue streams:

template <class charT, class traits, class T>
  basic_ostream<charT, traits>&
  operator<<(basic_ostream<charT, traits>&& os, const T& x);

1 Effects: os << x

2 Returns: os

This is good as it allows code that wants to (for example) open, write to, and close an ofstream all in one statement:

std::ofstream("log file") << "Some message\n";

However, I think we can easily make this "rvalue stream helper" even easier to use. Consider trying to quickly create a formatted string. With the current spec you have to write:

std::string s = static_cast<std::ostringstream&>(std::ostringstream() << "i = " << i).str();

This will store "i = 10" (for example) in the string s. Note the need to cast the stream back to ostringstream& prior to using the member .str(). This is necessary because the inserter has cast the ostringstream down to a more generic ostream during the insertion process.

I believe we can re-specify the rvalue-inserter so that this cast is unnecessary. Thus our customer now has to only type:

std::string s = (std::ostringstream() << "i = " << i).str();

This is accomplished by having the rvalue stream inserter return an rvalue of the same type, instead of casting it down to the base class. This is done by making the stream generic, and constraining it to be an rvalue of a type derived from ios_base.

The same argument and solution also applies to the inserter. This code has been implemented and tested.

[ 2009 Santa Cruz: ]

NAD Future. No concensus for change.

[LEWG Kona 2017]

Recommend Open: Design looks right.

[ 2018-05-25, Billy O'Neal requests this issue be reopened and provides P/R rebased against N4750 ]

Billy O'Neal requests this issue be reopened, as changing operator>> and operator<< to use perfect forwarding as described here is necessary to implement LWG 2534 which was accepted. Moreover, this P/R also resolves LWG 2498.

Previous resolution [SUPERSEDED]:

Change 27.7.4.5 [istream.rvalue]:

template <class charT, class traits Istream, class T>
  basic_istream<charT, traits>& Istream&&
  operator>>(basic_istream<charT, traits> Istream&& is, T& x);

1 Effects: is >> x

2 Returns: std::move(is)

3 Remarks: This signature shall participate in overload resolution if and only if Istream is not an lvalue reference type and is derived from ios_base.

Change 27.7.5.5 [ostream.rvalue]:

template <class charT, class traits Ostream, class T>
  basic_ostream<charT, traits>& Ostream&&
  operator<<(basic_ostream<charT, traits> Ostream&& os, const T& x);

1 Effects: os << x

2 Returns: std::move(os)

3 Remarks: This signature shall participate in overload resolution if and only if Ostream is not an lvalue reference type and is derived from ios_base.

Proposed resolution:

This resolution is relative to N4750.

Change 27.7.4.5 [istream.rvalue] as follows:

template <class charT, class traits Istream, class T>
  basic_istream<charT, traits>& Istream&&
  operator>>(basic_istream<charT, traits> Istream&& is, T&& x);

-1- Effects: Equivalent to:

is >> std::forward<T>(x)
return std::move(is);

-2- Remarks: This function shall not participate in overload resolution unless the expression is >> std::forward<T>(x) is well-formed, Istream is not an lvalue reference type, and Istream is derived from ios_base.

Change 27.7.5.5 [ostream.rvalue]:

template <class charT, class traits Ostream, class T>
  basic_ostream<charT, traits>& Ostream&&
  operator<<(basic_ostream<charT, traits> Ostream&& os, const T& x);

-1- Effects: As if by: os << x;

-2- Returns: std::move(os)

-3- Remarks: This signature shall not participate in overload resolution unless the expression os << x is well-formed, Ostream is not an lvalue reference type, and Ostream is derived from ios_base.