Can't we manage std :: map <string, ofstream>?

I tried to create to output sync results and call any of the threads from a predefined string:

#include <cstring>                                                                                                                  
#include <map>
#include <fstream>

using namespace std;

int main(void) {
    map<string,ofstream> Map;
    ofstream ofs("test_output");
    string st="test";
    Map[st] = ofs;
    return 0;
}

      

I got the following error; how can i fix this?

a.cpp: In function ‘int main()’:
a.cpp:11:8: error: use of deleted function ‘std::basic_ofstream<_CharT, _Traits>& std::basic_ofstream<_CharT, _Traits>::operator=(const std::basic_ofstream<_CharT, _Traits>&) [with _CharT = char; _Traits = std::char_traits<char>]’
  Map[s]=ofs;
        ^
In file included from a.cpp:3:0:
/usr/include/c++/5/fstream:744:7: note: declared here
   operator=(const basic_ofstream&) = delete;

       ^
In file included from a.cpp:3:0:
/usr/include/c++/5/fstream:744:7: note: declared here
   operator=(const basic_ofstream&) = delete; 

      

+3


source to share


2 answers


Since it is std::ostream

not copied (copy constructor and assignment operator are marked as deleted), you need to either build the stream directly on the map (for example using std::map::emplace()

) or use move assignment.

Build in place

Basically there are two ways, the default is to build the stream on the map (pre C ++ 11) or call std::map::emplace()

to provide constructor arguments ofstream

.

Using default build (works even up to C ++ 11):

map<string,ofstream> m;

// default-construct stream in map    
ofstream& strm = m["test"];
strm.open("test_output");
strm << "foo";

      

Using placement:

// 1st parameter is map key, 2nd parameter is ofstream constructor parameter    
auto res = m.emplace("test", "test_output");
auto& strm = res.first->second;
strm << "bar";

      

Move destination



First, we can build a stream outside of the map, turn it into an rvalue by calling std::move()

and use the move assignment operator to move it to the map:

map<string,ofstream> m;    
ofstream strm("test_output");
m["test"] = std::move( strm );
// strm is not "valid" anymore, it has been moved into the map

      

We can even get rid of std::move()

if we directly create the stream as an rvalue :

m["test"] = ofstream("test_output");

      

Transfer assignment is less efficient than other methods because the stream will be configured as the default on the map first, instead it will be replaced by the traffic assigned stream.

Live demonstration of all three methods.

Note. ... A sample example helps reduce errors for brevity. The state of the stream should be checked after opening and after each operation of the stream.

+4


source


This is due to the fact that you cannot copy ostream

, you can only transfer it. You are getting this error because the copy assignment operator has been removed. Instead, the card must own the stream:

Map[st] = std::move(ofs);

      



This now also means that you have to be careful when repeating your card. You must avoid copies and also avoid stealing property from the map.

Please note that is using namespace std;

not recommended.

+4


source







All Articles