0

I have a vector of pointers to structs, and want to check for existing items and sort by the value of a struct member. However, it appears that the check for existing items (I'm using QVector::indexOf()) is not working, and that std::sort is applying its sorting to some pointer value rather than the member value. I don't understand why the struct operator overloads aren't getting called (or called properly).

In header file:

struct PlotColumn {
    quint32 octagonLength;
    QVector<Qt::GlobalColor> columnVector;

    bool operator< (const PlotColumn& pc) const
    {
        return (this->octagonLength < pc.octagonLength);
    }
    bool operator==(PlotColumn const& pc)
    {
        return this->octagonLength == pc.octagonLength;
    }
    bool operator> (const PlotColumn& pc) const
    {
        return (this->octagonLength > pc.octagonLength);
    }
};
QVector<PlotColumn*> *plotMap;

In source file:

PlotColumn *pcNew = new PlotColumn();
pcNew->octagonLength = octagonLength;
// check if octagonLength has arrived before:
int plotXAxis = plotMap->indexOf(pcNew);
if (plotXAxis == -1) { // unknown, so insert:
     ... (some housekeeping)
     plotMap->append(pcNew);
     std::sort(plotMap->begin(), plotMap->end());
     ....
     (some more housekeeping)
}

Using an external (not in the struct) is possible for sort, but not for indexOf (afaik).

Any thoughts?

PS: yes I know there are tons of already answered questions about sorting vectors of pointers to structs and I've tried to apply the pattern in those solutions but it still doesn't work.

larslars
  • 168
  • 1
  • 14
  • For `std::sort` you could write the binary operators in terms of your member operators. Sort probably requires binary global operators. Also insted of having member operators you could have binary operators that are friends of your class. But that is just preference I guess. Also check [Comparison operators](http://stackoverflow.com/questions/4421706/operator-overloading/4421719#4421719) in this answer to see how you can write them in terms of each other. – rozina Sep 10 '15 at 12:43
  • 1
    You've also made the same mistake with `indexOf`, since you're searching for a pointer, not an object. I suspect you may be suffering from pointeritis: a tendancy to default to working with pointers when you really should be working with values or references instead. (also, I suspect even if pointers are right, you should be using smart pointers rather than bare pointers) –  Sep 10 '15 at 13:00
  • Thanks @Hurkyl, "pointeritis" gave me a good laugh! But you're probably right. Excellent lesson there. – larslars Sep 10 '15 at 14:15

3 Answers3

3

You need to provide a comparater to std::sort() that works with pointers.

bool PlotColumnPointerComparator(const PlotColumn *a, const PlotColumn *b)
{
     return (*a) < (*b);   // this will call your PlotColumn:: operator<()
}

And change your std::sort() statement to

std::sort(plotMap->begin(), plotMap->end(), PlotColumnPointerComparator);

In C++11, you could do the above with a lambda function, but that's just a syntactic convenience.

Compilers are not omnipotent mindreaders. If you tell it to sort a set of pointers, it will do pointer comparison. If you want the comparison to dereference the pointers and compare the pointed-to objects, you need to tell it to do that .... as in the above.

Peter
  • 35,646
  • 4
  • 32
  • 74
  • Thanks, I'm doing this but keeps getting the error "must use '.*' or '->*' to call pointer-to-member function in .... " – larslars Sep 10 '15 at 13:37
  • You've made the comparator a non-static member function. It needs to be a normal (non-member) function, or be a static member function of the class. – Peter Sep 10 '15 at 13:51
  • I did that, and I also made a similar static function to replace std::indexOf(..), which solves my problems! – larslars Sep 10 '15 at 14:14
0

std::sort is applying its sorting to some pointer value

Let's see:

QVector<PlotColumn*> *plotMap

std::sort(plotMap->begin(), plotMap->end());

Yep, that's exactly what you told std::sort to do (assuming QVector resembles vector): you have a container of pointers, told it to sort the elements of the container. Thus, you told it to sort pointers, not PlotColumn objects.

If you want to sort the pointers based on how the objects they point to compare, you have to apply one of those

answered questions about sorting vectors of pointers to structs

You've already identified your problem:

I've tried to apply the pattern in those solutions but it still doesn't work.

Don't give up on that line of inquiry: you've correctly identified something you need to work on, and should work to understand how those patterns work and how to apply them to your problem, and maybe ask a focused question regarding your attempts at that.

-1

It will not work because You are using the same signature. Overload works for different signatures. Check your function signatures.