output_iterator_tag and back_insert_iterator

Discussion in 'C++' started by Rares Vernica, Jun 21, 2008.

  1. 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::eek:utput_iterator_tag, T> data)
    {
    ....
    }

    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>

    If I change the function declaration to:

    template<class T, class OutputIterator>
    void readBinaryFile(
    const std::string &filename,
    OutputIterator data)

    it works fine.

    If possible, I would prefer to make the first declaration work
    somehow. Or at least, understand why it does not work.

    Thanks,
    Rares
     
    Rares Vernica, Jun 21, 2008
    #1
    1. Advertising

  2. Rares Vernica

    Kai-Uwe Bux Guest

    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::eek:utput_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
     
    Kai-Uwe Bux, Jun 21, 2008
    #2
    1. Advertising

  3. Rares Vernica

    Jerry Coffin Guest

    In article <>, says...

    [ ... ]

    > I defined the following function:
    >
    > template<class T>
    > void readBinaryFile(
    > const std::string &filename,
    > std::iterator<std::eek:utput_iterator_tag, T> data)
    > {
    > ...
    > }


    That was your first mistake... :)

    > Because the function is reading binary data, it needs to know the type of
    > the elements in the container, T.


    Yup.

    The function want is already implemented. It's called std::copy.

    All you need to do is write an extractor that extracts an item from your
    file correctly. The one problem is that there are already overloads to
    read the data incorrectly (i.e. from a text file) for many built-in
    types. You can overcome this by creating a proxy class, something like:

    template <class T>
    class binIO {
    T data;
    public:
    operator T() const { return data; }

    binIO(T value = T()) : data(value) { }

    friend std::istream &operator>>(std::istream &is, binIO &f) {
    return is.read((char *)&f.data, sizeof(f.data));
    }
    friend std::eek:stream &operator<<(std::eek:stream &os, binIO const &f) {
    return os.write((char *)&f.data, sizeof(f.data));
    }
    };

    To read (for example) a file of floats in binary format into a vector,
    you'd do something like:

    std::vector<float> data;
    std::ifstream in("input.dat", std::ios::binary);

    std::copy(std::istream_iterator<binIO<float> >(in),
    std::istream_iterator<binIO<float> >(),
    std::back_inserter(data));

    --
    Later,
    Jerry.

    The universe is a figment of its own imagination.
     
    Jerry Coffin, Jun 21, 2008
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Nut Cracker
    Replies:
    1
    Views:
    358
  2. jakk
    Replies:
    4
    Views:
    12,598
  3. Chyi Pin Lim

    value_type of a back_insert_iterator

    Chyi Pin Lim, Dec 5, 2003, in forum: C++
    Replies:
    9
    Views:
    543
    ppLiu_china
    Dec 11, 2003
  4. titi

    if and and vs if and,and

    titi, Mar 9, 2007, in forum: VHDL
    Replies:
    4
    Views:
    623
    Mike Treseler
    Mar 11, 2007
  5. Replies:
    14
    Views:
    1,404
    Triple-DES
    Feb 12, 2008
Loading...

Share This Page