views:

96

answers:

2

Thought it was pretty straight forward.

But I get a "iterator not dereferencable" errro when running the below code.

What's wrong?

template<typename T>
struct SumsTo : public std::binary_function<T, T, bool>
{
    int myInt;
    SumsTo(int a)
    {
        myInt = a;
    }
    bool operator()(const T& l, const T& r)
    {   
        cout << l << " + " << r;
        if ((l + r) == myInt)
        {
            cout << " does add to " << myInt;
        }
        else 
        {
            cout << " DOES NOT add to " << myInt;
        }
        return true;
    }
};

void main()
{
    list<int> l1;
    l1.push_back(1);
    l1.push_back(2);
    l1.push_back(3);
    l1.push_back(4);

    list<int> l2;
    l2.push_back(9);
    l2.push_back(8);
    l2.push_back(7);
    l2.push_back(6);

    transform(l1.begin(), l1.end(), l2.begin(), l2.end(), SumsTo<int>(10) );
}
+4  A: 

Your functor is fine. The problem is in the call to transform.

Transform has the prototype

transform(_InputIterator1 __first1, _InputIterator1 __last1,
          _InputIterator2 __first2, _OutputIterator __result,
          _BinaryOperation __binary_op)

your call is

transform(l1.begin(), l1.end(), l2.begin(), l2.end(), SumsTo<int>(10) );

instead of l2.end(), the fourth iterator argument needs to be the beginning of the result sequence. It should reference a sequence of objects that you can construct from bool.

If you want to save the results into l2, then you want

transform(l1.begin(), l1.end(), l2.begin(), l2.begin(), SumsTo<int>(10) );

As GMan suggests, another approach is std::back_inserter from <iterator>:

vector<bool> sums10; // vector<bool> is Good Enough for Me
transform(l1.begin(), l1.end(), l2.begin(), back_inserter(sums10), SumsTo<int>(10) );
Potatoswatter
I think you mean `back_inserter(sums10)`. :) No need to put my name in there, by the way.
GMan
@gman ah, thx, well no reason not to right…
Potatoswatter
@Potato: Sure, I don't mind. :) Some people just don't like other peoples names in there answers, and I'm not one to care if it is or isn't. Thanks, though. :]
GMan
Many thanks! :)
bobber205
A: 

As Potatoswatter pointed out, transform has the prototype

transform(_InputIterator1 __first1, _InputIterator1 __last1,
          _InputIterator2 __first2, _OutputIterator __result,
          _BinaryOperation __binary_op)

That means that the first two arguments indicate a range. In your case, l1.begin(), l1.end()

The next argument is the starting point of the next list: l2.begin()

The fourth argument is where your trouble is. It is asking for an "output" iterator, or somewhere to put the result of your operation. Instead, you're giving it the end of your second list.

Try this:

//...
list<bool> l3;

transform(l1.begin(), l1.end(), l2.begin(), back_inserter(l3), SumsTo<int>(10));

If that doesn't compile, try adding a #include <iterator>

What back_inserter does is it creates an iterator, that when written to (that's what makes it an "output" iterator) does a push_back with the value it's given to the container you pass it.

Austin Hyde
Better style to `#include` early to avoid uncertain dependencies…
Potatoswatter