🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

2 total messages Started by Nico Josuttis Thu, 11 Apr 1996 14:18
STL (specification) BUG: lost function object state in remove_if()
#3988
Author: Nico Josuttis
Date: Thu, 11 Apr 1996 14:18
44 lines
2797 bytes
Hi,
the big advantage of the usage of function objects with algorithms is,
that they have a state. But there is a problem, this state may get lost
IN THE MIDDLE of a running algorithm like remove_if().

This is due to the fact that the implementation calls two function:
 > template <class ForwardIterator, class Predicate>
 > ForwardIterator remove_if(ForwardIterator first, ForwardIterator last,
 >                           Predicate pred) {
 >   first = find_if(first, last, pred);
 >   ForwardIterator next = first;
 >   return first == last ? first : remove_copy_if(++next, last, first, pred);
 > }
But both, find_if() and remove_copy_if(), are called with call-by-value for
pred. This is a problem if for example i want to delete the first occurence
of a value. It results in removing the first and the second value, the first,
because find_if() finds it, the second because remove_copy_if() finds that
as first. Its pred doesn't know that find_if()s-pred has the state changed
into "found".
Tricky problem, isn't it ?

I think, we have to change algorithms here so that all internal calls
a made with call by reference.
If this results in prefomance penalties, we should implement the algorithm
in another way.

Anyway a big hint should be made in the specification either that this danger
exists or, if it is fixed, that the function object is the original object
operator() is called for every elem.

Any meanings ?
--------
Nico                             address: BREDEX GmbH
email:   nico@bredex.de                   Nicolai Josuttis
                                          Fallersleber-Tor-Wall 23
phone:   +49 531 24330-0                  D-38100 Braunschweig
fax:     +49 531 24330-99                 Germany
--------
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]
STL bug with example: remove_if() looses function state
#4113
Author: Nico Josuttis
Date: Fri, 19 Apr 1996 14:54
105 lines
3980 bytes
Some people asked for an example of my remove_if() problem.
Here is the problem with example.

The example uses remove_if() to remove only the first element
with a given value.
A function object (that has no side effects)
is designed to return true only for the first
element having a given value.
But using it as parameter of remove_if(), it is
duplicated and thus does return true twice.
That results in removing not only the first but also the
second element. OOOPS
 
------------------------- snip -----------
#include <iostream>
#include <list>
#include <algorithm>
using namespace std;

class FirstElemWithValue {
  private:
    int  value;
    bool found;
  public:
    FirstElemWithValue (int v) : value(v), found(false) {
    }
    bool operator() (int elem) {
	// return true only for the first found elem
        if (!found && elem == value) {
            found = true;
            return true;
        }
        return false;
    }
};

int main ()
{
    list<int> m;

    m.push_back (1);
    m.push_back (2);
    m.push_back (4);
    m.push_back (3);
    m.push_back (5);
    m.push_back (6);
    m.push_back (2);
    m.push_back (0);
    m.push_back (2);

    copy (m.begin(), m.end(), ostream_iterator<int>(cout," "));
    cout << endl;

    /* remove first element with value 2
     */
    list<int>::iterator pos;
    pos = remove_if (m.begin(), m.end(),
		     FirstElemWithValue(2));
    m.erase (pos, m.end());

    copy (m.begin(), m.end(), ostream_iterator<int>(cout," "));
    cout << endl;
}
------------------- snip --------------------------

The output is:
 1 2 4 3 5 6 2 0 2
 1 4 3 5 6 0 2
but should be:
 1 2 4 3 5 6 2 0 2
 1 4 3 5 6 2 0 2

This happens due to the current implementation of
remove_if() which calls find_if() and remove_copy_if():
 
 > template <class ForwardIterator, class Predicate>
 > ForwardIterator remove_if(ForwardIterator first, ForwardIterator last,
 >                           Predicate pred) {
 >   first = find_if(first, last, pred);
 >   ForwardIterator next = first;
 >   return first == last ? first : remove_copy_if(++next, last, first, pred);
 > }

So pred() is called with two different copies of
FirstElemWithValue.

I think it would be better/necessary to disallow such implementations,
what means to disallow that a function object gets copied before
calling operator().  At least it should not be allowed that operator()
is called by different copies of the function object.  Otherwise we
would lose the advantage of function objects in a significant matter.

Am I missing something ?

-- 
Nico                             address: BREDEX GmbH, Nicolai Josuttis
email:   nico@bredex.de                   Fallersleber-Tor-Wall 23
phone:   +49 531 24330-0                  D-38100 Braunschweig
fax:     +49 531 24330-99                 Germany
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads