21

Looking at previous answers on SO, it seems that while std::ostream is not be movable, std::ofstream should be. However, this code

#include <fstream>

int main()
{
    std::ofstream ofs;
    std::ofstream ofs2{std::move(ofs)};
}

does not seem to compile in any version of gcc or clang I tried (with either --std=c++11 or --std=c++14). The compiler error varies somewhat, but here's what I get for gcc 4.9.0

6 : error: use of deleted function 'std::basic_ofstream::basic_ofstream(const std::basic_ofstream&)'

Is this the expected behavior, according to the standard?

Note that a very similar question was asked before ( Is std::ofstream movable? ) but seems the standard has changed since then ( as detailed in Why can't std::ostream be moved? ) rendering those answers outdated. Certainly, none of those answers explains why the code above does not compile.

Came across this issue when trying to use containers of ofstream, which does not work because of the above.

Community
  • 1
  • 1
toth
  • 2,519
  • 1
  • 15
  • 23

1 Answers1

19

According to the standard

27.9.1.11 basic_ofstream constructors

or, its more "readable" version http://en.cppreference.com/w/cpp/io/basic_ofstream/basic_ofstream , std::basic_ostream<> has a move constructor, so the code should compile.

clang++ 3.5 compiles it with -std=c++11 or -std=c++1y. Also gcc5 compiles it, so probably it is not implemented in libstdc++ for gcc < 5

Interestingly, the lack of move semantics is not mentioned on gcc's stdlibc++ implementation https://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html#status.iso.2014

See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54316 for a bug report, thanks to @BoBTFish for pointing out. It is confirmed that the issue was fixed in gcc5.

vsoftco
  • 55,410
  • 12
  • 139
  • 252
  • 2
    https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54316 Note that at the top it only mentions `stringstream`, but further down it becomes clear this also applies to `ofstream`. And the bottom entry is "Fixed for GCC 5". – BoBTFish Feb 27 '15 at 23:06
  • Well, that seems pretty definitive. Had not tried gcc5, but did try clang 3.5 using http://gcc.godbolt.org/ and it did not work, guess it's an issue with that site. Thanks for your answer! – toth Feb 27 '15 at 23:18
  • @toth just glancing at your code in the link, I see that you are using `std::is_lvalue_reference_v`. AFAIK, there is no such `using` in C++11/14, so you have to use `std::is_value_reference::value`. I know, they should have defined it, similar to the type traits `_t` (from `<>::type`) – vsoftco Feb 28 '15 at 02:03