Re: output_iterator_tag and back_insert_iterator
Rares Vernica wrote:
Hello,
I am trying to write a generic function that can read data from a file
and store it in a container.
I defined the following function:
template<class T>
void readBinaryFile(
const std::string &filename,
std::iterator<std::output_iterator_tag, T> data)
{
...
}
You probably don't want that signature:
(a) When you pass an iterator, it will be sliced down to std::iterator,
which is a rather meaningless thing.
(b) Even if you fix that (e.g., passing the iterator by reference), you
would limit the use of your function to iterator types derived from
std::iterator< output_iterator_tag, T >. There are not that many.
You should consider:
template < typename T, typename InIter >
void readBinaryFile(
std::string const & filename,
InIter where ) {
....
}
which is much more versatile.
Because the function is reading binary data, it needs to know the type of
the elements in the container, T.
When I call it with something like:
vector<float> f;
readBinaryFile<float>("test.bin", back_inserter(f));
I get:
error: no matching function for call to ?readBinaryFile(std::string&,
std::back_insert_iterator<std::vector<float, std::allocator<float> > >)?
I am a little bit confused because I know that the back_insert_iterator
is an output iterator. In fact, back_insert_iterator is defined as:
template<typename _Container>
class back_insert_iterator
: public iterator<output_iterator_tag, void, void, void, void>
Note that float != void. You would want that back_inserter to be derived
from iterator< output_iterator_tag, float >, but that is _not_ what it is.
If I change the function declaration to:
template<class T, class OutputIterator>
void readBinaryFile(
const std::string &filename,
OutputIterator data)
it works fine.
Aha.
If possible, I would prefer to make the first declaration work
somehow.
No, you would not :-)
Or at least, understand why it does not work.
See above.
Best
Kai-Uwe Bux