Question

I'd like to use a std::unordered_map<unsigned,std::ofstream> but failed. Now I wonder whether this is simply impossible, or a compiler issue, or whether I just didn't get it right. The problem is the insertion of another element:

std::ofstream&get(unsigned key, std::unordered_map<unsigned,std::ofstream>&map)
{
  auto file = map.find(key);
  if(file==map.end()) {
    map.emplace(std::make_pair(key,std::ofstream{}));  // <-- trouble here
    file = map.find(key);
    assert(file!=map.end());
  }
  return file->second;
}

fails with gcc (4.8.1), because std::ofstream is not copy-constructible.

However, it is move-constructible, so there ought to be a solution, or not? (all I want to insert is a default-constructed std::ofstream). I tried to add some std::move()s, but that didn't help.

I just noted that the above code does compile with clang 3.4. Isn't this wrong?

Was it helpful?

Solution

you make a pair first then ask map to construct the pair again and cause the problem

try

map.emplace(key,std::ofstream{});

actually, all you need is

std::ofstream&get(unsigned key, std::unordered_map<unsigned,std::ofstream>&map)
{
  return map[key];
}

or remove this function... and use map[key]

because map will construct ofstream using default constructor if a non-exist key was used, so it should works like your code

OTHER TIPS

Its not related to GCC compiler either will all others presumably, basic_fstream offers fairly simple operations, on top of this file stream does not have copy operations. The solution is if you want two names to refer to the same file stream, use a reference or a pointer or manipulate file streambufs.

STL uses copy often, the above with emplace or make_pair uses copy little more convenient notation for insert(). The result of m[k] is equivalent to the result of (*(<map>.insert(make_pair(k,V{})).first)).second, where V is the mapped type, so there is no move in there.

Subtle difference to move and copy is that after a copy two objects must have the same value, whereas after a move the source of the move is not required to have its original value. Moves can be used when the source object will not be used again. They are particularly useful for implementing the notion of moving a resource.For the most interesting cases, containers, that moved-from state is “empty.”

There are five situations in which an object is copied or moved: • As the source of an assignment • As an object initialiser • As a function argument • As a function return value • As an exception In all cases, the copy or move constructor will be applied (unless it can be optimized away).

Reckon there is bleak chance to accommodate this in the current standard, that not over aforementioned in your case, could you not use a pointer to the ofstream?, like

unordered_map<int, ofstream*> map1;
map1.emplace(1, new ofstream());

Do you have any idea on other compilers which work with move?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top