Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How to overload operator< for QVector3D class



  • I'm using QVector3d with std::set and std::hypot. I'm receiving this error:

    /usr/include/c++/7/bits/stl_function.h:386:
    
    error: no operator "<" matches these operands
    
    operand types are: const QVector3D < const QVector3D
    
    { return __x < __y; }
    

    Is there a way to implement an overloaded operator< for QVector3D? I mean, without the need to compile all Qt from source!



  • std::set is a sorted associative set, which means it is created with a default predicate function of less_than or having (x<y) operator defined. The Qt QSet is an unsorted set and only uses the == operator to check if an item is already inserted in the set. Either switch to using QSet, or define a friend function for QVector3D::operator<(const QVector3D&) so that ordering of the vectors can take place.

    Actually you would subclass QVector3D, provide the operator overload for the subclass, and then you could use std::set<subclass>



  • I just replaced this:

    std::set<QVector3D> band{ *first, *last };
    

    with

    auto customComparator = [](QVector3D const &a, QVector3D const &b) { return a.y() < b.y(); };
    std::set<QVector3D, decltype (customComparator)> band({ *first, *last }, customComparator);
    

    then the error got resolved.



  • @m3g1dd

    That works too, more elegantly than subclassing QVector3D just to add an operator.



  • Trying to put a three dimensional vector type into a sorted data structure is almost certainly the wrong thing to want to do. Because three dimensional vectors can't be sorted in a useful way. It's the reason that (two dimensional) imaginary numbers can't be put on a one-dimensional number line, but then with an extra third dimension of nonsortability thrown in to be sure. My best guess is that if you try to use the "{ return a.y() < b.y(); };" custom comparator lambda, you will run into the problem that different vectors with the same Y coordinate will be rejected from the data structure. So trying to store (0,0,0), (1,0,0), (2,0,0) will leave you with only one vector in the std::set. It'll make the compile error go away, but only by creating wildly counterintuitive semantic problems.

    If you reeeeeeeally want to sort 3D vectors (of any sort, not just the QVector3D class specifically) then I'd suggest you look up space-filling curves and use the morton encoding of the position of the vector, since morton encoded vectors can be ordered. The ordering is almost completely arbitrary for most use cases, but it is ordered. (But, again, this is almost certainly the wrong thing to want to do in the first place.)

    If you use std::unordered_set instead of std::set, you can bypass the sorting issue.


Log in to reply