std::ifstream reader("file.dat", std::ios::binary);reader.seekg(0, std::ios::end);std::size_t data_size = reader.tellg();boost::scoped_array< char > data(new char[data_size]);reader.read(&data[0], data_size);
The closest you can come is to use istreambuf_iterators:std::ifstream reader("file.dat", std::ios::binary);std::istreambuf_iterator< char > begin(reader);std::istreambuf_iterator< char > end();std::vector< char > data(begin, end);
which performs multiple allocations and copies within the vector constructor for all but the smallest of files since istreambuf_iterator is only a model of InputIterator. Alternatively you can pre-allocate and read:std::ifstream reader("file.dat", std::ios::binary);reader.seekg(0, std::ios::end);std::vector< char > data(reader.tellg());reader.read(&data[0], data.size());
which redundantly initialises the entire vector to zero before overwriting with the file contents.Let's be clear. This is not a major issue from a performance point of view. We're talking about file I/O, which is orders of magnitude slower than anything that vector is doing. The issue is simply that there is a clear deficiency in the standard library, and worse, one without apparently any good reason for being there.
I messed around a bit looking for alternative solution using vector. It seemed clear to me that an iterator based solution would be cleanest, and that the only real problem with istreambuf_iterator is that it is unnecessarily generic. File streams support random access, whereas generic streams only support input/output iteration. I tried writing my own random access ifstreambuf_iterator and discovered that I couldn't. More surprisingly, the reason I couldn't implement it is because the C++ iterator abstraction is fundamentally broken. An istreambuf_iterator is not a model of RandomAccessIterator. It's a model of RandomAccessInputIterator, a concept unsupported by the C++ iterator abstraction model. The C++ iterator abstraction combines two orthogonal concepts, iteration and read/write access, into a single concept, without supporting all possible combinations.
Armed with this new-found knowledge I trawled the web (well, I typed a couple of brief queries into Google, but the former sounds more impressive) and unsurprisingly discovered that I was not the only one to have come to this conclusion. Reassuringly there is already a paper at the C++ Standards Working Group site that, also unsurprisingly, is much better thought out and goes into much more depth. The vector-from-file issue is one that has bugged me for quite some time. Now I can finally stop wondering if I'm missing some simple construct and rest in the knowledge that it simply needs fixing.
One of my co-workers stumbled across something interesting at work this week that had a few of us scratching our heads. Without consulting a compiler, what would you expect to result from the following code snippet?
#include struct Base1{ Base1() : a(1) { } int a;};template < typename Type >struct Base2{ Base2() : b(2), c(3) { } void function() { std::cout << b << '\n'; } Type b; Type c;};struct Derived : public Base1, public Base2< int >{ void function() { Base2::function(); }};int main(){ Derived d; d.function();}
?nigma