HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

Design for C++ class methods taking input from different sources

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
designmethodsinputdifferentforfromclasssourcestaking

Problem

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
void from_buffer(T* buffer, size_t len); // Read from a buffer and insert at end
template
void from_buffer(T* buffer, size_t len, iterator it); // Read from a buffer and insert at it

// The work is done here
template
void decode(InputIterator first, InputIterator last); // Decode range and insert at end
template
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".

Solution

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

std::vector   data;
 std::ifstream      file("Plop");

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

 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(bufferStream),  
                          std::istream_iterator());

 std::vector    anotherBuffer = LoadBuffer();
 data.insert(data.end(), std::begin(anotherBuffer), std::end(anotherBuffer));

Code Snippets

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));

Context

StackExchange Code Review Q#38824, answer score: 3

Revisions (0)

No revisions yet.