Reputation: 564
I tried to create for outputting the timing results and call any ofstream from pre-defined 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 it?
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;
Upvotes: 4
Views: 846
Reputation: 27776
As an std::ostream
is not copyable (copy constructor and assignment operator are marked deleted), you have to either construct the ofstream directly in the map (e.g. using std::map::emplace()
) or use move assignment.
There are basically two ways, either default-construct stream in the map (pre C++11), or call std::map::emplace()
to supply ofstream
constructor arguments.
Using default-construction (works even pre C++11):
map<string,ofstream> m;
// default-construct stream in map
ofstream& strm = m["test"];
strm.open("test_output");
strm << "foo";
Using emplacement:
// 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";
We can construct the stream outside of the map first, turn it into an rvalue by calling std::move()
and use move assignment operator to move it into 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");
Move assignment is less efficient than the other methods, because first a stream will be default-constructed in the map, just to be replaced by the move-assigned stream then.
Live demo of all three methods.
Note: Sample code omitts any error handling for brevity. State of stream should be checked after opening and after each stream operation.
Upvotes: 5
Reputation: 6086
This comes from the fact that you can't copy an ostream
you can only move it. You get this error because the copy assignment operator is deleted. Instead the map must take ownership of the stream:
Map[st] = std::move(ofs);
Now this also means that you will have to be careful when iterating over your map. You must avoid copies and also avoid stealing the ownership from the map.
On a side note, please note that using namespace std;
is not recommended.
Upvotes: 4