Search code examples
c++qtqhash

Qhash of Qhash reports error


I have written a function with qhash of qhash, which is shown below:

void scanOccurenceOnAllSequence(QString motif, QString chkMotif, qint32 offset, QString cell, QHash <QString, QHash <QString, QHash<qint32, qint32> > > *motifByCell2seq, QList<QString> *peakSequence){
    qint32 peakSequenceNumber = peakSequence->size();
    for(qint32 si=0; si < peakSequenceNumber; si++){
    if( motifByCell2seq->value(motif).value(cell).contains(si) ||  motifByCell2seq->value(motif).value(cell).contains(si) ){
        continue;
    }

    bool flag = checkMotifOccurence(motif,chkMotif,peakSequence->at(si),offset);

    if(flag){
        motifByCell2seq->value(motif).value(cell).insert(si,1);
    }
    }
}

However, there is an error on this line:

motifByCell2seq->value(motif).value(cell).insert(si,1);

The error is:

error: passing 'const QHash' as 'this' argument of 'QHash::iterator QHash::insert(const Key&, const T&) [with Key = int; T = int]' discards qualifiers [-fpermissive] motifByCell2seq->value(motif).value(cell).insert(si,1);

Even when I changed this line to the following, there is still an error

motifByCell2seq[motif][cell].insert(si,1);

Could you help me to find out the problem?


Solution

  • Short version: The value() method returns a const, so trying to do value().insert() is attempting to modify that constant value. operator[] can return a const and clearly in this case it is choosing to do so. If you assign motifByCell2seq[motif][cell] to a temporary variable, you can force the non-const operator[].

    Long version: As a strategy for working this out (aka, what I did to reach the short version above), I would break the problem line into pieces, assigning each to its own temporary variable.

    So, first it is worth simplifying. For instance, the bool flag line and the flag on the if statement are needed to recreate the error, so comment them out for now. Same for the if statement that is first in the for loop.

    So, currently, I've reduced the problem to:

    void scanOccurenceOnAllSequence(QString motif,
                                    QString chkMotif,
                                    qint32 offset,
                                    QString cell,
                                    QHash <QString, QHash<QString, QHash<qint32, qint32> > > *motifByCell2seq,
                                    QList<QString> *peakSequence)
    { 
        qint32 si=0;
        motifByCell2seq[motif][cell].insert(si,1);                                                                               
    }
    

    From there, I change replace the problem line with:

    QHash<QString, QHash<qint32, qint32> > tmp1;
    tmp1 = motifByCell2seq[motif];
    tmp1[cell].insert(si,1);
    

    And now the problem is still present and still in the last line, reducing the scope to search through.

    Another iteration takes me to:

        QHash<QString, QHash<qint32, qint32> > tmp1;
        tmp1 = motifByCell2seq[motif];
        QHash<qint32, qint32> tmp2;
        tmp2 = tmp1[cell];
        tmp2.insert(si,1);                                                                                    
    

    And that works. So, assigning the cell look-up to a temporary variable in this case changes the behavior. From there, I think I should double check the documentation for QHash, which is where I note the two versions of the operator[]. Also, I note that the value() method that you tried first only comes in a const version.

    Now that the problem is found, I would probably go back to:

    QHash<qint32, qint32> cellHash = (*motifByCell2seq)[motif][cell];
    cellHash.insert(si,1);
    

    And then of course, put the other stuff I removed back, and then write a test to confirm this is working as expected.