Opened 11 years ago

Closed 10 years ago

Last modified 10 years ago

#5825 closed Bugs (fixed)

constructing function_input_iterator without consuming an item

Reported by: Maximiliano Garrone ten Brink <maximiliano@…> Owned by: Dean Michael Berris
Milestone: To Be Determined Component: iterator
Version: Boost 1.47.0 Severity: Showstopper
Keywords: function_input_iterator past-the-end Cc: mikhailberis@…

Description

The only constructor for function_input_iterator always consumes an item from the generator. This makes it difficult to define a past-the-end iterator.

The first example given in http://www.boost.org/doc/libs/1_47_0/libs/iterator/doc/function_input_iterator.html calls rand() 11 times instead of the 10 expected. This can be a more serious problem when, for example, reading a file, as shown in the following program:

#include <string>
#include <fstream>
#include <iostream>
#include <algorithm>

#include <boost/iterator/function_input_iterator.hpp>

static const std::string filename( "test.txt" );

struct generator {
    typedef int result_type;
    generator() : in( filename ) {}

    result_type operator() () {
		result_type ret;
		in >> ret;
		return ret;
    }

	std::ifstream in;
};

int main(int argc, char * argv[]) {
	std::ofstream out( filename );
	out << 0 << std::endl
		<< 1 << std::endl
		<< 2 << std::endl
		<< 3 << std::endl;

    generator f;
    std::copy(
            boost::make_function_input_iterator(f, 0),
            boost::make_function_input_iterator(f, 3),
            std::ostream_iterator<int>(std::cout, " ")
        ); // "1 2 3" is shown on cout, instead of "0 1 2"
    return 0;
}

A possible solution could be adding a different constructor to function_input_iterator specifically to represent a past-the-end iterator.

Attachments (1)

boost-5825.patch (3.4 KB ) - added by Dean Michael Berris 10 years ago.
Fix to implementation and docs.

Download all attachments as: .zip

Change History (9)

comment:1 by charlie@…, 11 years ago

I have the same problem - here's a simple example where we try to emulate a boost counting iterator. What's particularly nasty is that the two calls to make_function_input_iterator are called in arbitrary order, so the behaviour isn't even defined, as either of the two iterators could end up with the first element.

#include <boost/iterator/function_input_iterator.hpp>
#include <boost/range/algorithm.hpp>
#include <iostream>
#include <vector>

class Counter
{
public:
  typedef int result_type;
  Counter(int initial)
  : m_val(initial)
  { }

  int operator()()
  {
    std::cout << "Returning: " << m_val << std::endl;
    return m_val++;
  }

private:
  int m_val;
};

int main()
{
  Counter c(10);
  std::vector<int> v;
  std::copy(boost::make_function_input_iterator(c, 0),
            boost::make_function_input_iterator(c, 5),
            std::back_inserter(v));
  boost::copy(v, std::ostream_iterator<int>(std::cout, " "));
  std::cout << std::endl;

  return 0;
}

Here's the output:

Returning: 10
Returning: 11
Returning: 12
Returning: 13
Returning: 14
Returning: 15
Returning: 16
11 12 13 14 15 

I believe the iterators should be modified to never invoke the generator initially until they are dereferenced (so in particular the second iterator should never invoke the generator if used as an end iterator).

comment:2 by Dave Abrahams, 11 years ago

Severity: ProblemShowstopper

I agree; this looks like a serious problem.

comment:3 by Dean Michael Berris, 10 years ago

Cc: mikhailberis@… added
Owner: changed from Dave Abrahams to Dean Michael Berris

I wasn't watching this and I've just gotten time to take a look at this now. Let me whip up a patch to fix this.

comment:4 by Dean Michael Berris, 10 years ago

Update: I have a patch ready locally, just getting the necessary approvals to release the code under the Boost Software License. If things go well I should have something late Pacific Time, Monday August 27.

by Dean Michael Berris, 10 years ago

Attachment: boost-5825.patch added

Fix to implementation and docs.

comment:5 by Dean Michael Berris, 10 years ago

The attached patch applies to Boost trunk.

comment:6 by Dean Michael Berris, 10 years ago

Status: newassigned

comment:7 by Dean Michael Berris, 10 years ago

Resolution: fixed
Status: assignedclosed

comment:8 by jeffrey.hellrung, 10 years ago

(In [80467]) fix #5825; fix #7194

Note: See TracTickets for help on using tickets.