代码之家  ›  专栏  ›  技术社区  ›  rbaleksandar

在结构列表上调用std::sort时,将const作为“this”参数传递错误

  •  0
  • rbaleksandar  · 技术社区  · 7 年前

    我有一个相当大的 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:错误:将“const Data::Journey”作为“bool Data::Journey::operator”的“this”参数传递(<(const Data::旅程)丢弃限定符[-fpermissive]

    我呼叫时出现此错误 标准::排序 在任何 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 为本地机器和目标系统的构建设置。也许我的rootfs目录(存储目标操作系统映像的地方)中的某个底层库太旧了?

    1 回复  |  直到 7 年前
        1
  •  0
  •   Patrick Avery    7 年前

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

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