Results 1 to 9 of 9

Thread: How can QMultiMap::contains() differ from QMultiMap::keys().contains()?

  1. #1
    Join Date
    Aug 2016
    Posts
    3
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Question How can QMultiMap::contains() differ from QMultiMap::keys().contains()?

    I have the following code:

    Qt Code:
    1. QList<QPersistentModelIndex> keys = indexToPlacemarkMap.keys();
    2. bool listLookup = keys.contains(QPersistentModelIndex(index));
    3. bool multimapLookup = indexToPlacemarkMap.contains(QPersistentModelIndex(index));
    To copy to clipboard, switch view to plain text mode 

    where index is a QModelIndex and indexToPlacemarkMap is a QMultiMap<QPersistentModelIndex,GeoDataPlacemark*> .

    In some cases listLookup = true and multimapLookup = false. I don't understand how this is possible. The documentation for QMultiMap::contains indicates that it searches the keys, so I would expect these two bools to always be equal. Can anyone explain to me why they might not be equal? QPersistentModelIndex(index) is checked for validity and it is valid.

    Don

  2. #2
    Join Date
    Jan 2012
    Location
    Dortmund, Germany
    Posts
    159
    Thanks
    69
    Thanked 10 Times in 8 Posts
    Qt products
    Qt4
    Platforms
    Windows Android

    Default Re: How can QMultiMap::contains() differ from QMultiMap::keys().contains()?

    Not sure, but I'll try:
    QMultiMap - as opposed to QMap - allows more than one value per key. If you ask for the keys(), you will not be given doublettes, right? But those doublettes will probably exist internally - each one with its own index.

    So if listLookup = true and multimapLookup = false, you simply have an index to a key, that is not part of .keys() method's output list, but rather pointing to a doublette with some other value.

  3. #3
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: How can QMultiMap::contains() differ from QMultiMap::keys().contains()?

    Not sure, but I'll try
    I don't think that's right. The code posted deals only with the keys, not the values stored by them.

    Lines 2 and 3 each construct a temporary QPersistentModelIndex; the call to indexToPlacemarkMap.keys() in line 1 also creates a temporary QList<> of QPersistentModelIndex instances, using the QPersistentModelIndex copy constructor.

    So you have potentially three different instances of QPersistentModelIndex you are trying to compare. I don't know if it is necessarily true that two QPersistentModelIndex instances that point to the same QModelIndex will compare as equal using the version of QPersistentModelIndex::operator==() that compares two QPersistentModelIndex instances.

    That is:

    Qt Code:
    1.  
    2. assert( a == index ); // Should be true
    3. assert( b == index ); // Should also be true
    4. assert( a == b ); // But is this true?
    To copy to clipboard, switch view to plain text mode 

    In lines 2 and 3 of your code, try replacing "QPersistentModelIndex( index )" with just "index"; then you will be invoking the version of QPersistentModelIndex::operator==() that compares the two wrapped QModelIndex instances for equality.
    Last edited by d_stranz; 27th August 2016 at 01:58.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  4. The following user says thank you to d_stranz for this useful post:

    sedi (27th August 2016)

  5. #4
    Join Date
    Aug 2016
    Posts
    3
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: How can QMultiMap::contains() differ from QMultiMap::keys().contains()?

    Quote Originally Posted by d_stranz View Post
    In lines 2 and 3 of your code, try replacing "QPersistentModelIndex( index )" with just "index"; then you will be invoking the version of QPersistentModelIndex::operator==() that compares the two wrapped QModelIndex instances for equality.
    Thanks, d_stranz. That is actually how the code was originally written, and it exhibits this behavior as well. I had added the casting to QPersistentModelIndex when debugging the behavior to see if that was the issue, but it was not.

    My original debug code looked something like this:

    Qt Code:
    1. foreach(QPersistentModelIndex map_pindex, indexToPlacemarkMap.keys() )
    2. {
    3. QModelIndex debugIndex = QModelIndex(map_pindex);
    4. if(debugIndex == index)
    5. {
    6. bool itsInThere = true;
    7. }
    8. if(!indexToPlacemarkMap.contains(map_pindex))
    9. {
    10. bool lookupFailed = true;
    11. }
    12. }
    To copy to clipboard, switch view to plain text mode 

    where I was seeing cases where itsInThere was true but lookupFailed was also true. The fact that I could iterate over the keys but have the contains method fail was what led me to see that there seemed to be a difference in the contains method behavior on the keys QList vs QMultiMap.

  6. #5
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: How can QMultiMap::contains() differ from QMultiMap::keys().contains()?

    I had added the casting
    Well, in this case, it isn't actually casting, it's calling the QPersistentModelIndex constructor that takes a QModelIndex as argument. That probably has some subtly different behavior than a pure type cast between two first-class types (eg. int to double).

    QModelIndex debugIndex = QModelIndex(map_pindex);
    I am surprised this compiles. There is no constructor for QModelIndex that takes a QPersistentModelIndex as argument, and the compiler won't let you cast between dissimilar types.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  7. #6
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: How can QMultiMap::contains() differ from QMultiMap::keys().contains()?

    Quote Originally Posted by d_stranz View Post
    I am surprised this compiles. There is no constructor for QModelIndex that takes a QPersistentModelIndex as argument, and the compiler won't let you cast between dissimilar types.
    QPersistentModelIndex has a cast operator to QModelIndex, so the compiler chose that to convert map_pindex into a QModelIndex and passed that to the QModelIndex copy constructor.
    http://doc.qt.io/qt-5/qpersistentmod...odelIndex--and

    @donalbane: have you tried how QMultiMap behaves with a simple key type, e.g. int?

    Cheers,
    _

  8. The following user says thank you to anda_skoa for this useful post:

    d_stranz (30th August 2016)

  9. #7
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: How can QMultiMap::contains() differ from QMultiMap::keys().contains()?

    QPersistentModelIndex has a cast operator to QModelIndex
    I looked and look for that and somehow didn't see it in the list of methods. I knew there had to be something like that.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  10. #8
    Join Date
    Aug 2016
    Posts
    3
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: How can QMultiMap::contains() differ from QMultiMap::keys().contains()?

    Quote Originally Posted by anda_skoa View Post
    @donalbane: have you tried how QMultiMap behaves with a simple key type, e.g. int?
    @anda_skoa: Most of the time QMultiMap works as expected. We are just seeing a particular state encountered with QPersistentModelIndex keys that exhibits the strange behavior. I wasn't sure if it was a bug or if what I was seeing was normal and I just did not understand the expected behavior. Were I to construct a sample test using int keys, or even QPersistentModelIndex keys, I'm sure that it would work as expected. But, I still don't understand how what I am seeing is possible.

  11. #9
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: How can QMultiMap::contains() differ from QMultiMap::keys().contains()?

    One cause would be if the model had changed while the map is filled.

    I.e. if the model changes, then the persistent model indexes get updated.
    Which could lead to new value regarding the sorting criteria of the map, which would make the map inconsistent.

    Extracting all keys doesn't need the sorting to be intact, but a contains lookup does.

    I.e. you can still iterate over the data even if it is not a map anymore, but using map functionality is only possible as long as the map's invariant is still valid.

    Cheers,
    _

Similar Threads

  1. Replies: 0
    Last Post: 2nd September 2015, 18:50
  2. passing QMultiMap to Q_ARG?
    By hunsrus in forum Qt Programming
    Replies: 7
    Last Post: 13th September 2012, 22:39
  3. Replies: 1
    Last Post: 30th August 2011, 02:01
  4. QMultiMap And QDataStream
    By amiref in forum Qt Programming
    Replies: 1
    Last Post: 30th March 2011, 10:50
  5. Delete auto pointer from QMultiMap
    By phillip_Qt in forum Qt Programming
    Replies: 5
    Last Post: 3rd December 2007, 17:29

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.