views:

95

answers:

3

Hello!

I am now diving into boost::iostreams and I'm looking for a way to create a stream that iterates over some container<char>.

Right now I have the code that work for a std::vector<char>, but it does ONLY for it, because I wrote std::vector-specific code.

I am doing the following thing:

template <class Object, class Container>
void Load(Object& object, const Container& container) {

   using namespace boost::iostreams;

   // Create a stream that iterates over vector and use it in
   // the following procedure
   LoadImpl(object, stream<array_source>(&container[0], container.size()));
}

where LoadImpl(...) is described the following way:

template <class Object
void LoadImpl(Object& object, std::istream& stream) { ... }

and is used to wrap serializing / deserializing using some certain stream.

Could you give me any advice on how to make Load routine more generic? Let's say, I would like to have an ability to substitute std::vector<char> to it as long as some std::string container.

+3  A: 

Instead of passing the container as a parameter to your functions, what about using the approach taken by the standard library, and use iterators?

Your function would be templated on the iterator type instead of the container type and would take a begin and end iterator instead of a container. Then it's a simple matter to iterate over the range for any container type you give it.

Mark B
Yep - A lot of c++ std::libs make a lot more sense when you realize they should only operate on iterators.
Martin Beckett
+1  A: 

The direct answer is not to use iterators. I think the people before me misunderstood that this is a boost::iostreams-specific question.

I'm not an expert on boost::iostreams, but your Load routine is already somewhat generic and should work with std::string as well (provided you resize it accordingly in advance to hold the stream buffer). However, by using the array_source device, I believe you're going by the assumption that the container is randomly-accessible. This will not work for std::list, for instance. For that, I'm not sure what the correct device is, but another one is needed which works using iterators.

+1  A: 

I would suggest you look at the facilities provided by the standard lib.
It has a whole host of iterator adapters that help you manipulate containers.

// Copy a stream into a vector
std::vector<char>  vec;    // This could be any container the
                           // code below would still work.
std::copy(std::istreambuf_iterator<char>(std::cin),
          std::istreambuf_iterator<char>(),
          std::back_inserter(vec)
         );

It is not just the iterators but the utility methods that you use to create the iterators that just make the whole thing a simple dream to use.

Martin York