Modify

Opened 6 years ago

Closed 5 years ago

Last modified 5 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 5 years ago.
Fix to implementation and docs.

Download all attachments as: .zip

Change History (9)

comment:1 Changed 6 years ago by charlie@…

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 Changed 6 years ago by Dave Abrahams

Severity: ProblemShowstopper

I agree; this looks like a serious problem.

comment:3 Changed 5 years ago by Dean Michael Berris

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 Changed 5 years ago by Dean Michael Berris

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.

Changed 5 years ago by Dean Michael Berris

Attachment: boost-5825.patch added

Fix to implementation and docs.

comment:5 Changed 5 years ago by Dean Michael Berris

The attached patch applies to Boost trunk.

comment:6 Changed 5 years ago by Dean Michael Berris

Status: newassigned

comment:7 Changed 5 years ago by Dean Michael Berris

Resolution: fixed
Status: assignedclosed

comment:8 Changed 5 years ago by jeffrey.hellrung

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

Modify Ticket

Change Properties
Set your email in Preferences
Action
as closed The owner will remain Dean Michael Berris.
The resolution will be deleted.

Add Comment


E-mail address and name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.