Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can I use `operator<<` on temporary std::ofstream objects?

According to the C++ standard you cannot bind a temporary to a non-const reference. Since the stream output operator is defined as

template <class CharT, class Traits, class Allocator>

std::basic_ostream<CharT, Traits>&
    operator<<(std::basic_ostream<CharT, Traits>& os,
               const std::basic_string<CharT, Traits, Allocator>& str);

I would expect it to not be callable on temporary stream objects. However, I tried the following and got unexpected results

#include <fstream>

std::ostream& print(std::ostream &stream) {
    stream << "test\n";
    return stream;
}

int main() {
    std::fstream("") << "test\n";
    // print(std::fstream("")); // Doesn't compile, as expected
}

This compiles on GCC trunk, Clang trunk and MSVC 19. I even tried -pedantic-errors on the first two. While technically possible that all three are wrong, it is likely that I am misunderstanding something.

Can somebody find a definitive answer in the standard on whether this is legal C++ or not?

like image 836
patatahooligan Avatar asked Sep 10 '19 09:09

patatahooligan


2 Answers

There is overload which takes stream by Rvalue reference:

template< class CharT, class Traits, class T >
basic_ostream< CharT, Traits >& operator<<( basic_ostream<CharT,Traits>&& os,
                                        const T& value );

temp is passed as os. From reference.

like image 101
rafix07 Avatar answered Sep 20 '22 06:09

rafix07


The C++ standard mandates the following function template existing (C++17 n4659 30.7.5.5 [ostream.rvalue]):

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

With effects specified as os << x.

Note that the same exists for extraction (>>) as well.

like image 34
Angew is no longer proud of SO Avatar answered Sep 22 '22 06:09

Angew is no longer proud of SO