Click to See Complete Forum and Search --> : Debuggin a Simple STL Algorithm :: STL


kuphryn
October 25th, 2002, 02:09 AM
Hi.

I would like to debug a simple algorithm that does not work using an STL solution. The solution works via iteration.

std::list<unsigned int> theList;

for (unsigned int i = 0; i < 10; ++i)
theList.push_back(i);

// theList should now contain 0, 1, 2, 3, 4, 5, 6, 7, 8, and 9.

// Remove "6" from the list.
// Assume that iTheList is an iterator that points to element with value 6.

theList.erase(iTheList);

// After erase() theList should now contain 0, 1, 2, 3, 4, 5, 7, 8, and 9.

Okay. Everything above works as designed. Now I would like to decrement everything bigger or equal to "6," thus make theList hold 0, 1, 2, 3, 4, 5, 6, 7, 8, and 9. Here is the iterative solution.


// Given iTheList points to theList.begin().

while (*iTheList <= 6)
++iTheList

// Now decrement until end of theList.

while (*iTheList != theList.end()
{
*iTheList = *iTheList - 1;
++iTheList;
}


The iterative solution above works perfect.

I would like to implement a more efficient and elegant solution. Here is one solution using STL algorithms. However, it does not work correctly.


std::for_each(std::find_if(theList.begin(), theList.end(), std::bind2nd(std::greater<>, 6)), theList.end(), std::bind2nd(std::minus<>, 1));


The STL solution above does not work. The logic and syntec seem to be valid.

Is there a logic or syntec misunderstanding in the STL solution? I looked over the function objects and function adapter. They are valid.

Thanks,
KUphryn

Graham
October 25th, 2002, 03:52 AM
I think your problem is in instantiating the greater and minus functions (I'll split the code because I think it reads better that way):

std::list<unsigned int>:: iterator i =
std::find_if(theList.begin(), theList.end(), std::bind2nd(std::greater<unsigned int>(), 6));

std::for_each(i, theList.end(), std::bind2nd(std::minus<unsigned int>(), 1));

kuphryn
October 25th, 2002, 10:22 AM
Okay. Thanks.

Fruny posted a solution at GameDev using transform().

http://www.gamedev.net/community/forums/topic.asp?topic_id=120974

In general, what is the problem of my original STL solution?

Kuphryn

kuphryn
October 25th, 2002, 11:10 AM
Okay. I added a class object that will do the minus manually.


template <typename T>
class DecreaseOne : public std::binary_function<T, T, void>
{
public:
void operator()(T &lp, const T &rp)
{
lp -= rp;
}
};

[/code]

Here the call to it.


std::for_each(std::find_if(theList.begin(), theList.end(), std::bind2nd(std::greater<size_t>(), 6)), theList.end(), std::bind2nd(DecreaseOne<size_t>(), 1));


The compiler will not compile. Here is the errors.


error C2064: term does not evaluate to a function
error C2662: 'DecreaseOne<unsigned int>::operator`()'' : cannot convert 'this' pointer from 'const DecreaseOne<T>' to 'DecreaseOne<T> &'
with
[
T=size_t
]
and
[
T=size_t
]


I defined DecreaseOne functor as a global class.

What is the problem?

Thanks,
Kuphryn

Graham
October 25th, 2002, 01:08 PM
std::for_each is classed as a non-mutating algorithm, meaning it's not allowed to change the value that the iterator points to. The other poster was correct to suggest std::transform, which is a mutating algorithm.

kuphryn
October 25th, 2002, 01:55 PM
ahhhhh. Okay. Thanks.

Kuphryn