linux - 在结构列表上调用 std::sort 时将 const 作为 'this' 参数错误传递

标签 linux qt sorting std cross-compiling

我有一个相当大的 struct称为 Journey :

typedef struct Journey
{
    /**
      * @brief The InfoText struct is a container for storing messages (short and long) that are found
      * inside a journey's <InfoTextLists/> as <InfoText/> elements
      */
    typedef struct InfoText
    {
        QString shortMsg;
        QString longMsg;

        InfoText(QString shortMsg, QString longMsg)
        {
            this->shortMsg = shortMsg;
            this->longMsg = longMsg;
        }

        bool operator ==(const InfoText &other)
        {
            return (this->shortMsg == other.shortMsg) && (this->longMsg == other.longMsg);
        }

        bool operator !=(const InfoText &other)
        {
            return !(*this == other);
        }
    } InfoText;


    QTime arrivalNextImmediateStop;             //!< Arrival time (planned). It can be found under Time inside Arr in XML reply
    QTime arrivalNextImmediateStopRelative;     //!< Arrival time (relative, @p arrivalNextImmediateStop + @p delay)

    // Departure data
    QTime departure;            //!< Departure time (planned). It can be found under Time inside Dep in XML reply
    quint32 departureRelative;  //!< Departure time (relative and in minutes, @p departure + @p delay - current time)
    int delay;                  //!< Departure time delay (minutes). It can be found under Delay inside Dep in XML reply

    // Transfer time
    // TODO Calculate this at the beginning of the data fusion slotGetData(). It is required for the display of the connection (remaining time column)
    QTime transferTime;         //!< Transfer time based on the CSV L and V files. Required for the lookup filter (see @ref Data::Filtering::FilterFutureLookup)

    // Direction and destination data
    quint8 direction;           //!< Run direction (1, 2). It can be found under Attribute of type DIRECTIONFLAG in XML reply
    QString directionTarget;    //!< Run direction final destination. It can be found under Attribute of type DIRECTION in XML reply

    QString operatorJ;          //!< Full name of operator of the journey (Berliener Verkehrsbetriebe, DB Regio AG ...). It can be found under Attribute of type OPERATOR in XML reply
    QString vehicleType;        //!< Type of the vehicle (B, F, U, S ...). It can be found under Attribute with of type CATEGORY in XML reply
    QString line;               //!< The line of the vehicle (for example: 109 (for Bus 109), S5 (for S-Bahn 5) etc.). It can be found under Attribute of type NUMBER in XML reply

    // Immedidate stops data
    quint32 immediateStop1;     //!< First immediate stop ID (without offset) after current station
    quint32 immediateStop2;     //!< Second immediate stop ID (without offset) after current stations

    bool dirty;                 //!< Used by the secondary filtering mechanism this value shows whether the given connection has been marked for removal or not

    /**
     * @brief Stores all <InfoText/> element found inside the journey's <InfoTextLists/> element. An info text is a message consisting of a headline (short message)
     *        and a body (long message)
     */
    QList<InfoText> infoTexts;


    /**
     * @brief Constructor
     */
    Journey()
    {
        this->arrivalNextImmediateStop = QTime();
        this->arrivalNextImmediateStop = QTime();
        this->departure = QTime();
        this->departureRelative = 0;
        this->transferTime = QTime();
        this->delay = this->direction = this->immediateStop1 = this->immediateStop2 = 0;
        this->directionTarget = this->operatorJ = this->vehicleType = this->line = "";
        this->dirty = false;
    }

    /**
     * @brief Allows comparing for equality between two journeys
     * @param other Journey to compare with
     * @return True if arrival time to both next two immediate stops, departure time, relative departure
     *         time, delay, direction, destination, journey operator, vehicle type, line and IDs of next
     *         two immediate stops are equal
     */
    bool operator ==(const Journey &other)
    {
        return arrivalNextImmediateStop == other.arrivalNextImmediateStop
                && arrivalNextImmediateStopRelative == other.arrivalNextImmediateStopRelative
                && departure == other.departure
                && departureRelative == other.departureRelative
                && delay == other.delay
                && direction == other.direction
                && directionTarget == other.directionTarget
                && operatorJ == other.operatorJ
                && vehicleType == other.vehicleType
                && line == other.line
                && immediateStop1 == other.immediateStop1
                && immediateStop2 == other.immediateStop2;
    }

    /**
     * @brief Allows comparing for inequality between two journeys
     * @param other
     * @return True if arrival time to both next two immediate stops, departure time, relative departure
     *         time, delay, direction, destination, journey operator, vehicle type, line and IDs of next
     *         two immediate stops are not equal
     */
    bool operator !=(const Journey &other)
    {
        return !(*this == other);
    }

    /**
     * @brief Overloads the < operator to allow sorting journeys in a ascending order based on their line. Due to the alphanumeric nature of
     *        most lines special handling is required to ensure proper order. With the default string comparison namely own_line < other_line the result
     *        is in most cases not correct: M10, M5, M8 instead of M5, M8, M10. Using @ref alphanumericLineSplitRx an attempt is made to split the line
     *        into two distrinctive tokens - alphabetic and numeric. If the split does not succeed the line is made only of letter or digits in which case
     *        standard string comparison can be used. On the other hand if it does succeed, we need to do a comparison of each of the two tokens. In some
     *        cases lines can be the same in which case the direction of both is used for the comparison
     * @param other A journey with a line
     * @return True if line of journey is smaller (string comparison or numeric comparison if lines are of alphanumeric or only numeric nature) than line of @p journey
     */
    bool operator < (const Journey &other)
    {
        QRegularExpressionMatch matchesOwn = alphanumericLineSplitRx.match(this->line);
        QRegularExpressionMatch matchesOther = alphanumericLineSplitRx.match(other.line);

        // Figure out if the lines of our own and the other journey are complex (alphanumeric) or simple (just alphabetic or just numeric)
        // If we have alphanumeric lines we need to split each line into two tokens - alphabetic and numeric
        if (matchesOwn.capturedTexts().length() == 3 && matchesOther.capturedTexts().length() == 3)
        {
            QString lineAlphaOwn = matchesOwn.captured(1);
            QString lineAlphaOther = matchesOther.captured(1);
            quint16 lineNumericOwn = matchesOwn.captured(2).toUInt();
            quint16 lineNumericOther = matchesOther.captured(2).toUInt();

            // If the alphabetic token of both journies are different there is not need to compare the numeric token and
            // standard string comparison is used
            // Example: N20, M100 will be sorted as M100, N20 since M comes before N
            if (lineAlphaOwn != lineAlphaOther)
            {
                return this->line < other.line;
            }

            // If the alphabetic token is the same for both lines the numeric token is the next criterion for sorting
            // Example: N10, N1, N2, N20 will be sorted as N1, N2, N10, N20
            if (lineNumericOwn != lineNumericOther)
            {
                return lineNumericOwn < lineNumericOther;
            }

            // If both the alphabetic and the numeric tokens are the same the direction will be used as the sorting criterion
            // Example: N10 (direction 2), N10 (direction 1) will be sorted as N10 (direction 1), N10 (direction 2)
            return this->direction < other.direction;
        }

        // In case the matching has failed this means that the line consists either of just a single alphabetic or numeric
        // The numeric-only case needs to be handled to avoid sorting results like 1, 100, 1000, 2, 20, 2000 ...
        bool isOwnNumericOnly = false;
        bool isOtherNumericOnly = false;
        quint16 lineNumericOwn = matchesOwn.captured(1).toUInt(&isOwnNumericOnly);
        quint16 lineNumericOther = matchesOther.captured(1).toUInt(&isOtherNumericOnly);

        if (isOwnNumericOnly && isOtherNumericOnly)
        {
            // In case the line (digits only!) of both journies are different, we use standard numeric comparison
            // Example: 206, 815, 413 will be sorted as 206, 413, 815
            if (lineNumericOwn != lineNumericOther)
            {
                return lineNumericOwn < lineNumericOther;
            }

            // Both journies have the same number for a line so the direction is used as the sorting criterion
            // Example: 280 (direction 2), 280 (direction 1) will be sorted as 280 (direction 1), 280 (direction 2)
            return this->direction < other.direction;
        }
        else
        {
            // In case the line (letters only!) of both journies are different, we use standard string comparison
            // Example: S, TXL, R will be sorted as R, S, TXL
            if (this->line != other.line)
            {
                return this->line < other.line;
            }

            // Both journies have the same letter for a line so the direction is used as the sorting criterion
            // Example: TXL (direction 2), TXL (direction 1) will be sorted as TXL (direction 1), TXL (direction 2)
            return this->direction < other.direction;
        }
    }

    /**
     * @brief Overloads the > operator to allow sorting journeys in a ascending order based on their line. Internally the overloaded
     * @ref operator < and @ref operator != operators are used
     * @param other A journey with a line
     * @return True if line of journey is greater (string comparison or numeric comparison if lines are of alphanumeric or only numeric nature) than line of @p journey
     */
    bool operator > (const Journey &other)
    {
        return (*this != other) && (*this < other);
    }

    /**
     * @brief Checks if the journey belongs to a specific vehicle type
     * @param vehicleType Type of vehicle to check own affiliation with
     * @return True if journey belongs to @p vehicleType
     */
    bool belongsToVehicleType(QString vehicleType)
    {
        return this->vehicleType == vehicleType;
    }
} Journey;

它存储从服务器的 HTTP GET 回复中检索到的数据,该服务器提供有关各种车辆及其穿过城市的路线的信息。

我正在使用的规范中的一项要求在我过滤了一次无效(基于各种标准)后导致了庞大的重载 < 之后,为旅程提供了一个不那么简单的排序机制。您在上面的代码片段中看到的运算符(其他在这里并不重要)。

我必须将所有可用行程分成更小的组(根据车辆类型,这就是 belongsToVehicleType() 函数的用途)。对于每组旅程,我必须运行 std::sort以实现该数据所需的顺序。

长话短说 - 在我的本地机器(32 位 Ubuntu 16.04 和 Qt 5.4.2)上一切正常,但是当我尝试交叉编译它时(目标系统也使用 Qt 5.4.2,基于 Intel 的 32 位架构等.).请注意,如果我注释掉所有我称之为 std::sort() 的行即使使用交叉编译器,我的代码似乎也能正常编译(尽管链接器提示由于某种原因无法找到 libc.so.6)。您可以在下面看到 Qt Creator 输出的错误消息:

/opt/target-toolchain/crosstools/i686-unknown-linux-gnu/i686-unknown-linux-gnu/include/c++/4.7.4/bits/stl_algo.h:2277: error: passing 'const Data::Journey' as 'this' argument of 'bool Data::Journey::operator<(const Data::Journey&)' discards qualifiers [-fpermissive]

当我调用 std::sort 时出现此错误在任何QList与各自的旅程有关。例如:

QList<Journey> connectionsRE;

// Fill connectionsRE

if (connectionsRE.length())
{
    LOG(INFO) << "Regional train (Express) RE1-RE9 connections:";
    std::sort(connectionsRE.begin(), connectionsRE.end());  // <----------- ERROR STARTS FROM HERE!!!

    // Do something else with connectionsRE
}

运行时的完整编译错误make在项目的构建文件夹中是

In file included from /opt/target-toolchain/crosstools/i686-unknown-linux-gnu/lib/gcc/i686-unknown-linux-gnu/4.7.4/../../../../i686-unknown-linux-gnu/include/c++/4.7.4/algorithm:63:0,
                 from /opt/target-toolchain/Qt/Qt5/include/QtCore/qglobal.h:81,
                 from /opt/target-toolchain/Qt/Qt5/include/QtCore/qnamespace.h:37,
                 from /opt/target-toolchain/Qt/Qt5/include/QtCore/qobjectdefs.h:41,
                 from /opt/target-toolchain/Qt/Qt5/include/QtCore/qobject.h:40,
                 from /opt/target-toolchain/Qt/Qt5/include/QtCore/QObject:1,
                 from /home/user/Projects/project/src/datafusionhandler.h:4,
                 from /home/user/Projects/project/src/datafusionhandler.cpp:1:
/opt/target-toolchain/crosstools/i686-unknown-linux-gnu/lib/gcc/i686-unknown-linux-gnu/4.7.4/../../../../i686-unknown-linux-gnu/include/c++/4.7.4/bits/stl_algo.h: In instantiation of '_RandomAccessIterator std::__unguarded_partition(_RandomAccessIterator, _RandomAccessIterator, const _Tp&) [with _RandomAccessIterator = QList<Data::Journey>::iterator; _Tp = Data::Journey]':
/opt/target-toolchain/crosstools/i686-unknown-linux-gnu/lib/gcc/i686-unknown-linux-gnu/4.7.4/../../../../i686-unknown-linux-gnu/include/c++/4.7.4/bits/stl_algo.h:2315:70:   required from '_RandomAccessIterator std::__unguarded_partition_pivot(_RandomAccessIterator, _RandomAccessIterator) [with _RandomAccessIterator = QList<Data::Journey>::iterator]'
/opt/target-toolchain/crosstools/i686-unknown-linux-gnu/lib/gcc/i686-unknown-linux-gnu/4.7.4/../../../../i686-unknown-linux-gnu/include/c++/4.7.4/bits/stl_algo.h:2347:54:   required from 'void std::__introsort_loop(_RandomAccessIterator, _RandomAccessIterator, _Size) [with _RandomAccessIterator = QList<Data::Journey>::iterator; _Size = int]'
/opt/target-toolchain/crosstools/i686-unknown-linux-gnu/lib/gcc/i686-unknown-linux-gnu/4.7.4/../../../../i686-unknown-linux-gnu/include/c++/4.7.4/bits/stl_algo.h:5483:4:   required from 'void std::sort(_RAIter, _RAIter) [with _RAIter = QList<Data::Journey>::iterator]'
/home/user/Projects/project/src/datafusionhandler.cpp:387:61:   required from here
/opt/target-toolchain/crosstools/i686-unknown-linux-gnu/lib/gcc/i686-unknown-linux-gnu/4.7.4/../../../../i686-unknown-linux-gnu/include/c++/4.7.4/bits/stl_algo.h:2277:4: error: passing 'const Data::Journey' as 'this' argument of 'bool Data::Journey::operator<(const Data::Journey&)' discards qualifiers [-fpermissive]
compilation terminated due to -Wfatal-errors.
src/CMakeFiles/project.dir/build.make:134: recipe for target 'src/CMakeFiles/project.dir/datafusionhandler.cpp.o' failed
make[2]: *** [src/CMakeFiles/project.dir/datafusionhandler.cpp.o] Error 1
CMakeFiles/Makefile2:1018: recipe for target 'src/CMakeFiles/project.dir/all' failed
make[1]: *** [src/CMakeFiles/project.dir/all] Error 2
Makefile:94: recipe for target 'all' failed
make: *** [all] Error 2

-Wfatal-errors为我的本地机器和目标系统的build设置。也许我的 rootfs 目录(存储目标操作系统镜像的位置)中的某些底层库太旧了?

最佳答案

我认为您可能需要将某些运算符函数声明为 const,例如:

bool operator > (const Journey &other) const
{
  ...
}

关于linux - 在结构列表上调用 std::sort 时将 const 作为 'this' 参数错误传递,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47576227/

相关文章:

linux - 在 GNU/Linux 中,匹配文件中的模式并使用找到的字符串提取包含另一个文件中的字符串的行

c++ - 在信号槽机制与传统循环之间做出决定

c++ - Qt - QTreeView 和 SQL - 性能建议

c - 使用函数对动态数组进行冒泡排序

c# - 如何在 ListView 处于 VirtualMode 时对 ListView 项目进行排序?

Linux stdout stderr 重定向到文件 : different from terminal output

java - 分析 Linux 上的 Java 内存使用情况

python - 如何在读取时不写入文件,反之亦然

qt - 保存 QGraphicsScene 图像

objective-c - 我怎样才能做一个不区分大小写的 NSFetchedResultsController 类型,它也忽略像 "the"这样的词?