15

The following example program doesn't compile for me on either clang 3.1 or gcc 4.8:

#include <fstream>
#include <vector>

using namespace std;

int main()
{
    vector<ifstream> bla;
    bla.emplace_back("filename");
    return 0;
}

However, I thought emplace_back should

"Insert a new element at the end of the vector, right after its current last element. This new element is constructed in place using args as the arguments for its construction."

Does anyone know why this doesn't compile then? did I misunderstand or are the library implementations not yet complete?

R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
dgel
  • 164
  • 2
  • 8

3 Answers3

15

Streams in c++11 are movable, so in theory you should be able to do what you want, problem is that movable streams have not yet been implemented in gcc/libstdc++.

To back up my answer further please take a look at gcc/libstdc++ c++11 status: http://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html#status.iso.2011

Especially 27.5, 27.8, 27.9

7

That's a bug in the implementation of std::basic_istream. It should be movable, but isn't; and only movable types can be stored in a vector.

Here is the bug report against GCC.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • Thanks, that explains then. Shouldn't you also be able to store copyable types in a vector though, even if they aren't moveable? – dgel Jun 13 '13 at 15:30
  • 1
    @dgel: streams aren't copyable, either (neither in C++98 or C++11). – HighCommander4 Jun 13 '13 at 15:39
  • @HighCommander4: I know, but I was commenting on his general statement that 'only movable types can be stored in a vector', which may be confusing. – dgel Jun 13 '13 at 16:01
  • 1
    @dgel: Copyable types *are* movable. "Movable" means that you can create an object that's the same as an existing object (possibly invalidating the existing object); "Copyable" means you can do that without changing the existing object. – Mike Seymour Jun 13 '13 at 16:28
  • @Mike Seymour: Thanks, I thought movable meant that it implemented move semantics, whereas a copyable type might not implement the relevant move-related functions. – dgel Jun 14 '13 at 11:11
0

Since it isn't fixed yet (AFAIK), here's a quick workaround:

typedef std::shared_ptr<std::ifstream> SharedIFS;
inline SharedIFS MakeIFS(const std::string &file) {
    return SharedIFS(new std::ifstream(file));}

Unless I missed something stupid, the SharedIFS should be moveable and copyable just fine. It has some overhead compared to plain emplace_back, but at least you can put it into a vector.

Autolykos
  • 203
  • 2
  • 8