Modify

Ticket #5825 (closed Bugs: fixed)

Opened 3 years ago

Last modified 20 months ago

constructing function_input_iterator without consuming an item

Reported by: Maximiliano Garrone ten Brink <maximiliano@…> Owned by: mikhailberis
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

boost-5825.patch Download (3.4 KB) - added by mikhailberis 20 months ago.
Fix to implementation and docs.

Change History

comment:1 Changed 2 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 2 years ago by dave

  • Severity changed from Problem to Showstopper

I agree; this looks like a serious problem.

comment:3 Changed 20 months ago by mikhailberis

  • Cc mikhailberis@… added
  • Owner changed from dave to mikhailberis

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 20 months ago by mikhailberis

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 20 months ago by mikhailberis

Fix to implementation and docs.

comment:5 Changed 20 months ago by mikhailberis

The attached patch applies to Boost trunk.

comment:6 Changed 20 months ago by mikhailberis

  • Status changed from new to assigned

comment:7 Changed 20 months ago by mikhailberis

  • Status changed from assigned to closed
  • Resolution set to fixed

comment:8 Changed 20 months ago by jeffrey.hellrung

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

View

Add a comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
The resolution will be deleted. Next status will be 'reopened'
Author


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

 
Note: See TracTickets for help on using tickets.