7

In an example with vector<int> someVector and istringstream someStringStream you can do this:

for (int i=0; i < someVector.size(); i++) {
  someStringStream >> someVector[i];
}

I know that vector<bool> is an efficient implementation, and operator[] returns a reference object. For this code I should be using an index rather than an iterator, mostly for readability. Currently, I'm using this:

for (int i=0; i < someVector.size(); i++) {
  bool temp;
  someStringStream >> temp;
  someVector[i] = temp;
}

Is there a more direct way of implementing this?

2 Answers2

5

You could use std::copy or the std::vector range constructor if you want to consume the whole stream:

std::stringstream ss("1 0 1 0");
std::vector<bool> vec;
std::copy(std::istream_iterator<bool>(ss), {}, std::back_inserter(vec));

LIVE DEMO

std::stringstream ss("1 0 1 0");
std::vector<bool> vec(std::istream_iterator<bool>(ss), {});

LIVE DEMO

Now looking at the examples that you posted and if you're sure that your std::vectors size is proper you could use std::generate like the example below:

std::stringstream ss("1 0 1 0");
std::vector<bool> vec(4);
std::generate(std::begin(vec), std::end(vec), [&ss](){ bool val; ss >> val; return val;});

LIVE DEMO

101010
  • 41,839
  • 11
  • 94
  • 168
0

If all you want is the same interface for bool and other types, it's easy to wrap things.

template <typename T>
T read(std::istream& stream)
{
   T value;
   stream >> value; // TODO: guard against failure of extraction, e.g. throw an exception.
   return value;
}

However, using this directly requires you to specify a type.

for (int i=0; i < someIntVector.size(); i++)
{
   someIntVector[i] = read<int>(someStringStream);
}

for (int i=0; i < someBoolVector.size(); i++)
{
   someBoolVector[i] = read<bool>(someStringStream);
}

If you reuse that for several different vectors, just wrap it again:

template <typename T, typename A>
void fillVectorFromStream(std::istream& stream, std::vector<T, A>& vector)
{
    for ( int i = 0; i < vector.size(); ++i )
    {
        vector[i] = read<T>(stream);
    }
}

Hence, usage simply becomes

fillVectorFromStream(streamOfBool, vectorOfBooleanValues);
fillVectorFromStream(streamOfIntegers, vectorOfIntegers);
stefan
  • 10,215
  • 4
  • 49
  • 90
  • This is not safe. If operator >> fails, then "value" will be uninitialized. Either the stream state should be checked explicitly, or std::ios_base::failbit should be ORed to the stream's exceptions(). – Arne Vogel Jun 04 '15 at 12:25
  • 1
    @ArneVogel This changed in C++11: if extraction fails, zero is written to value (see http://en.cppreference.com/w/cpp/io/basic_istream/operator_gtgt). However, I do agree that error checking is necessary in production code. Still, there are so many ways to do that. It's not the scope of the question to choose one, imho. – stefan Jun 04 '15 at 12:32