3
\$\begingroup\$

I have a class foo that needs to get input from different sources, namely input streams, arrays and iterators. The code that actually does the work in the end takes iterators as input, and all the other methods end up calling it behind the scenes:

void from_stream(std::istream& in); // Read from stream and insert at end
void from_stream(std::istream& in, iterator it); // Read from stream and insert at it

template<typename T>
void from_buffer(T* buffer, size_t len); // Read from a buffer and insert at end
template<typename T>
void from_buffer(T* buffer, size_t len, iterator it); // Read from a buffer and insert at it

// The work is done here
template<typename InputIterator>
void decode(InputIterator first, InputIterator last); // Decode range and insert at end
template<typename InputIterator>
void decode(InputIterator first, InputIterator last, iterator it); // Decode range and insert at it

I want users to be able to make calls like these (assume foo class is initially empty):

Foo foo;
foo.from_stream(my_stream, foo.begin()); // or without foo.begin()
foo.from_buffer(my_buffer, buflen, foo.begin() + 4); // same...

and internally the code will call specialized std::inserter, std::front_inserter or std::back_inserter functions as appropriate and pass them to foo::decode. I could just use std::inserter all the time, but I would think it is more efficient to use std::back_inserter when foo.end() is passed and so on.

I could change the iterator argument to a template parameter and let the user decide what kind of iterator to use similar to the STL (which is actually what I am trying to aim for). This would also allow the user to pass a foo::iterator and overwrite content instead of inserting data. This would change the calls above to:

foo.from_stream(my_stream, std::back_inserter(foo));
foo.from_buffer(my_buffer, buflen, std::inserter(foo, foo.begin() + 4));

I could use some design advice about what approach, or another one entirely, is "best".

\$\endgroup\$
3
\$\begingroup\$

Why not just insert() and iterator like most containers in the STL.

 std::vector<int>   data;
 std::ifstream      file("Plop");

 data.insert(data.end(), std::istream_iterator<int>(file),
                         std::istream_iterator<int>());

 char  buffer[] = "1 2 3 4 5 6 6 7 8 9 10 11 12 13 14 15 16 17 18 19";
 std::stringstream   bufferStream(buffer);

 data.insert(data.end(), std::istream_iterator<int>(bufferStream),  
                          std::istream_iterator<int>());


 std::vector<int>    anotherBuffer = LoadBuffer();
 data.insert(data.end(), std::begin(anotherBuffer), std::end(anotherBuffer));
\$\endgroup\$
  • \$\begingroup\$ I was too focused on my own interface to realize this. It is so much simpler and preferably STL-like, thanks! However, when passing data.end(), I would still need to create a std::back/front- or inserter to actually insert the data. \$\endgroup\$ – NordCoder Jan 10 '14 at 11:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.