2328. Rvalue stream extraction should use perfect forwarding

Section: 30.7.4.5 [istream.rvalue] Status: C++17 Submitter: Stephan T. Lavavej Opened: 2013-09-21 Last modified: 2017-07-30

Priority: 3

View all other issues in [istream.rvalue].

View all issues with C++17 status.

Discussion:

30.7.4.5 [istream.rvalue] declares operator>>(basic_istream<charT, traits>&& is, T& x). However, [istream::extractors]/7 declares operator>>(basic_istream<charT,traits>& in, charT* s), plus additional overloads for unsigned char* and signed char*. This means that "return_rvalue_istream() >> &arr[0]" won't compile, because T& won't bind to the rvalue &arr[0].

[2014-02-12 Issaquah : recategorize as P3]

Jonathan Wakely: Bill was certain the change is right, I think so with less certainty

Jeffrey Yaskin: I think he's right, hate that we need this

Jonathan Wakely: is this the security issue Jeffrey raised on lib reflector?

Move to P3

[2015-05-06 Lenexa: Move to Review]

WEB, MC: Proposed wording changes one signature (in two places) to take a forwarding reference.

TK: Should be consistent with an istream rvalue?

MC: This is the case where you pass the stream by rvalue reference.

RP: I would try it before standardizing.

TK: Does it break anything?

RP, TK: It will take all arguments, will be an exact match for everything.

RS, TK: This adapts streaming into an rvalue stream to make it act like streaming into an lvalue stream.

RS: Should this really return the stream by lvalue reference instead of by rvalue reference? ⇒ new LWG issue.

RP: Security issue?

MC: No. That's istream >> char*, C++ version of gets(). Remove it, as we did for gets()? ⇒ new LWG issue.

RS: Proposed resolution looks correct to me.

MC: Makes me (and Jonathan Wakely) feel uneasy.

Move to Review, consensus.

[2016-01-15, Daniel comments and suggests improved wording]

It has been pointed out by Tim Song, that the initial P/R (deleting the Returns paragraph and making the Effects "equivalent to return is >> /* stuff */;") breaks cases where the applicable operator>> doesn't return a type that is convertible to a reference to the stream:

struct A{};
void operator>>(std::istream&, A&){ }

void f() {
  A a;
  std::istringstream() >> a; // was OK, now error
}

This seems like an unintended wording artifact of the "Equivalent to" Phrase Of Power and could be easily fixed by changing the second part of the P/R slightly as follows:

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

-1- Effects: Equivalent to:is >>x

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

-2- Returns: is

Previous resolution [SUPERSEDED]:

This wording is relative to N4567.

  1. Edit [iostream.format.overview], header <istream> synopsis, as indicated:

    namespace std {
      […]
      template <class charT, class traits, class T>
        basic_istream<charT, traits>&
        operator>>(basic_istream<charT, traits>&& is, T&& x);
    }
    
  2. Edit 30.7.4.5 [istream.rvalue] as indicated:

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

    -1- Effects: Equivalent to return is >>x std::forward<T>(x)

    -2- Returns: is

[2016-03 Jacksonville: Move to Ready]

Proposed resolution:

This wording is relative to N4567.

  1. Edit [iostream.format.overview], header <istream> synopsis, as indicated:

    namespace std {
      […]
      template <class charT, class traits, class T>
        basic_istream<charT, traits>&
        operator>>(basic_istream<charT, traits>&& is, T&& x);
    }
    
  2. Edit 30.7.4.5 [istream.rvalue] as indicated:

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

    -1- Effects: Equivalent to:is >>x

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

    -2- Returns: is