Why can I std :: move the rvalue ref stream to lvalue ref?

As far as I understand C ++ 11 links, I should not bind the rvalue link to a (not const) lvalue link, since the former can be tied to a temporary one, and the latter should never be linked to a temporary one.

However, I found this strange behavior in combination with temporary stream objects (which I reduced as much as I could)

struct Dummy {};
template <typename Stream>
Stream& operator<<(Stream& s, Dummy) {
  return s << ".";          // <- (A)
}

template <typename Stream>
void pass(Stream&& s) {
  std::move(s) << Dummy();  // <- (X)   rvalue->lvalue conversion?
}

#include <fstream>
int main() {
  pass(std::fstream("test",std::ios::out));
}

If I write s << Dummy()in a string (X), C ++ complains about the string (A), saying

error: invalid initialization of reference of type β€˜std::basic_fstream<char>&’ from expression of type β€˜std::basic_ostream<char>’

However, why does the code (as shown above) compile and work as expected? Link Rvalue return std::moveshould be as simple as it may not be associated with the name referring to an expression sthere, but both gcc 4.6.1and gcc 4.7.2react the same way.

? Dummy&& , , T& , std::move.

+5
1

basic_ostream operator<<, :

template <typename Elem, typename Traits, typename T>
basic_ostream<Elem, Traits>&
    operator<<(basic_ostream<Elem, Traits>&& sink, const T& val)
{
    return sink << val;
}

" Rvalue" , Β§27.7.3.9 [ostream.rvalue].

( ) rvalue basic_ostream lvalue. , , .


, :

Stream& operator<<(Stream& s, Dummy) , Stream std::fstream, std::ostream (.. basic_ostream<char>).

basic_ostream<E, T>& operator<<(basic_ostream<E, T>&, const char*) , , ostream. std::ostream& std::fstream&, .

, s (, ).

, rvalue-to-lvalue, . basic_ostream, Stream , .

+10

All Articles