Is std::ofstream movable?
Asked Answered
S

2

10

I have this map which compiles fine in MSVC10 :

std::map<std::string, std::ofstream> m_logFiles;

But on ubuntu using g++ 4.5 with C++0x enabled, I get the following error message :

/usr/include/c++/4.5/bits/ios_base.h|785|error: ‘std::ios_base::ios_base(const std::ios_base&)’ is private

By using pointers instead of objects, I resolved the problem.
Searching on the web, I learned that streams are not meant to be copied (the why was well explained). But my question is, is std::ofstream a movable type ? If it is, shouldn't it allow its use as a template parameter in the standard containers ?
If yes, then is g++ behind MSVC10 on this point ? (which would explain why it works on MSVC). I know it would be silly to ask compiler writers to fully implement something that isn't even final, but I'm curious regarding the future.

Using g++ 4.6.1 didn't help.

Edit : reading the comments I dug a little bit further and found that the insert is causing the problem, not the declaration of the map.

Reading Cubbi's link I tried the following :

#include <string>
#include <fstream>
#include <map>

using namespace std;

int main()
{
    map<string, ofstream> m_logFiles;
    ofstream st;
    m_logFiles.insert(make_pair<string, ofstream>(string("a"), move(st)));
    return 0;
}

But still no luck. g++ complains about the use of b deleted copy constructor.

Streeto answered 15/8, 2011 at 15:14 Comment(2)
The posted code compiles fine in GCC 4.5.3 as well. However, GCC's library (unlike clang's libc++) has not yet implemented map.emplace() gcc.gnu.org/bugzilla/show_bug.cgi?id=44436 -- perhaps that's what caused the error message?Lives
@Lives : I read your link and tried using std::move, but no change.Streeto
I
8

std::ofstream is movable. This program compiles for me using clang/libc++:

#include <string>
#include <fstream>
#include <map>

int main()
{
    std::map<std::string, std::ofstream> m_logFiles;
}

Reference 27.9.1.11 [ofstream.cons].

Inesita answered 15/8, 2011 at 15:21 Comment(10)
The result on any one compiler (or even many compilers) does not really answer this question. A reference to the spec is needed.Gerianne
@Gerianne - Howard is the person implementing the standard library for this compiler. I'd trust him.Nepheline
Check pretty much all of section 27 of the C++0x draft. I didn't find a single place which says "ofstream shall be movable", but it specifies that the stream classes have move constructors and move assignment operators and all the other move-related plumbing. So yes, they're movable, as @Howard said. :)Indignation
@Bo: Thanks Bo. Fwiw, I'm also the person who made osftream movable. If it isn't, I'm going to be in a really bad mood. :-)Inesita
@Nemo: Kidding aside, you are quite correct. I've added a reference.Inesita
@Howard : I checked, and yes, the declaration compiles fine, it's in fact the insert that is causing the problem. I tried using std::move, but I don't understand what I'm doing wrong.Streeto
@Jonathan: I don't think you're doing anything wrong. Your insert compiles for me, and I don't see anything wrong with it. But pair has been thrashed to death, so maybe it isn't up to spec. Try emplace: m_logFiles.emplace(string("a"), move(st));Inesita
@Howard : std::map doesn't have the emplace method yet in g++ 4.6.1. Well, I have a workaround and you gave me valuable information, I'll just wait for g++ c++0x support (and its standard library) to continue to evolve.Streeto
Unfortunately, until g++-4.9 the move constructors are not working for std::fstream. Below simple program doesn't compile with g++-4.9, but compiles fine with g++-5: #include<fstream> #include<vector> struct A { std::fstream m_File; }; int main () { std::vector<A> vA; vA.push_back(A{}); } Any idea how to fix it for older versions of compilers?Vonnievonny
@iammilind: The only workaround I can think of is unique_ptr<fstream> which will (and should) leave a bad taste in your mouth. :-\Inesita
S
6

I asked a similar question earlier, and later found that GCC doesn't seem to support movable fstreams yet (I just tested GCC 4.6.1) as detailed in this answer.

Skerl answered 17/8, 2011 at 1:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.