AnotherUser
AnotherUser

Reputation: 1353

Casting from an iterator to a defined type?

I am trying to construct a loop that will loop over a std::vector of typedef std::pair<double, double> CFPoint to produce sets of two points to work on.

if(pointList.size() % 2 == 0)
{
    CFPoint first = NULL;
    CFPoint second = NULL;
    for (std::vector<CFPoint>::const_iterator it = pointList.begin(); it != pointList.end(); ++it)
    {
        TRACE("APoint: %f, %f\n", it->first, it->second);

        if(first == NULL && second == NULL)
            {first = it; continue;}
        if(first != NULL && second == NULL)
            second = it;
        if(first != NULL && second != NULL)
        {
            double transitLen = sqrt(  pow((second.first - first.first), 2) + pow((second.second - first.second), 2) );
            TRACE("Distance between points: %f\n", transitLen);

            first = NULL;
            second = NULL;
        }
    }
}

Reviewing the code you might see that I use = NULL to signify that a CFPoint variable is either "ready" or not to be used. My problem is that NULL is defined as 0 in C++ and I cannot assign 0 to a CFPoint. There also is no null keyword in C++.

What might my options be to set my variables as "null" or something like that to achieve the loop above?

Hmm, while I was writing this I had the idea to use pointers in my loop rather than actual variables. You can set a pointer to NULL. The only issue is when trying to set first and second. I've tried to set my first by doing first = &it; but it is of type iterator how can I cast it to CFPoint*?

Upvotes: 0

Views: 341

Answers (5)

PeterSW
PeterSW

Reputation: 5261

The way of structuring the solution seems to be making it more complicated than is probably necessary (Jarod42's solution shows a simpler way). Running with it though you should be able to get it working by using pointList.end() as your guard value:

if(pointList.size() % 2 == 0)
{
    typedef std::vector<CFPoint>::const_iterator ConstPointIterator;

    const ConstPointIterator guardValue(pointList.end());

    ConstPointIterator first = guardValue;
    ConstPointIterator second = guardValue;

    for (ConstPointIterator it = pointList.begin(); it != pointList.end(); ++it)
    {
        TRACE("APoint: %f, %f\n", it->first, it->second);

        if(first == guardValue && second == guardValue)
            first = it; continue;
        if(first != guardValue && second == guardValue)
            second = it;
        if(first != guardValue && second != guardValue)
        {
            double transitLen = sqrt(  pow((second.first - first.first), 2) + pow((second.second - first.second), 2) );
            TRACE("Distance between points: %f\n", transitLen);

            first = guardValue;
            second = guardValue;
        }
    }
}

Upvotes: 0

Andrei
Andrei

Reputation: 19

Well, your task actually doesn't require a 'null' value for a point, all you need is iterate over pairs of vector elements.

How about this:

if (pointList.size() % 2 == 0)
{
    for (std::vector<CFPoint>::const_iterator it = pointList.begin(); it != pointList.end(); it += 2)
    {
        TRACE("APoint: %f, %f\n", it->first, it->second);

        CFPoint first = *it;
        CFPoint second = *(it+1);

        double transitLen = sqrt(pow((second.first - first.first), 2) + pow((second.second - first.second), 2));
        TRACE("Distance between points: %f\n", transitLen);
    }
}

Upvotes: 1

Jarod42
Jarod42

Reputation: 217145

You may do something like:

if (pointList.size() % 2 == 0)
{
    for (std::size_t i = 0; it != pointList.size(); i += 2)
    {
        const CFPoint& first = pointList[i];
        const CFPoint& second = pointList[i + 1];
        TRACE("APoint: %f, %f\n", first.first, first.second);
        TRACE("APoint: %f, %f\n", second.first, second.second);
        const double transitLen = sqrt(pow((second.first - first.first), 2) + pow((second.second - first.second), 2) );
        TRACE("Distance between points: %f\n", transitLen);
    }
}

Upvotes: 2

it->first and it->second are not pointers. They are both double. So what you are doing here:

if(first == NULL && second == NULL)

is checking if they are equal to 0.

Not even it is a pointer, it is a CFPoint and not CFPoint.

And

CFPoint first = NULL; CFPoint second = NULL;

Are also not pointers, that is why you cannot set them to NULL. Try:

CFPoint* first = NULL; CFPoint* second = NULL;

instead, and also use std::vector.

Or do this:

typedef typedef std::pair<double, double>* CFPoint

Upvotes: 0

James Kanze
James Kanze

Reputation: 153909

The obvious problem is that std::pair<double, double> doesn't have a sentinal value and the names of its components are probably not appropriate either. (There's also the problem that you've named it in a way which suggests that it is part of MFC.) You should define your type as a class, with provisions for a null value, if that's what you need. This can be done either by adding an additional bool which indicates whether the value is valid or not, or by doing something tricky with NaNs. (The first is to be preferred, at least at the start. The second should be reserved as an optimization measure.)

Upvotes: 0

Related Questions