GetDefault function for QMap and other keyed containers

  • The QMap class already has the functionality to return a default value if an item isn't found at the specified key. This is found in
    const T QMap::value ( const Key & key, const T & defaultValue ) const":

    This functionality is very useful, but I often find with keyed collections like a map, that I would like to insert an item with some default value at a given key. I usually implement some sort of getDefault() function. This could be defined as such:

    /** Gets a value associated with a key from the QMap.

    • If no entry matching the key is found, the default value is inserted and returned
    • @param key - The key with which to look up the item
    • @param defaultValue - The default value to insert if the associated key is not found in the map
    • @return A reference to the value associated with the given key.
    •     If there was no value at the key, this will be a reference to the newly added default value

    const T& QMap::getDefault( const Key& key, const T& defaultValue );

    I have added this as a suggestion in the bugtracker, but I was interested to know what other developers think of this sort of functionality. What sort of problems could this introduce, and why don't we see this sort of functionality added with many implementations of keyed containers in Qt and other libraries?

  • I find the concept a bit awkward and the name totally misleading. A "getFoo()" method that modifies the object? Not very intuitive in my book. one could have insertIfNotExistant() or sth like that, but it would still appear as API clutter to me. What is your use case where this would make more sense than value() with default value?

  • In which case do you want to use this function? I guess, it's redundant function.
    @if ( !QMap.contains( key ) )
    QMap.insert(key, defValue)
    T = QMap[key];@
    It's simple.

  • I don't get the use case for this function either. What is the use of storing the default value in the keyed container at all? It sounds much more efficient to me not to store data points that have the default value. If you want something else there than the default, then it obviously isn't the default value.

    However, I must say that I implemented a matrix class once, and for that class I did find it was useful to set a default value explicitly. However, that value was not inserted into the data backend, it was just returned if there was not actual data in the internal storage. I am wondering if that is more efficient than passing a constructed value of the correct type each time, especially if that type is a bit more complex than a basic data type?

  • @ Alexander -- Admittedly, it is easy to explicitly code this sort of functionality. As you pointed out, it is three lines of code. However, if this sort of functionality is needed in more than one place, it would be nice to package it into a single function call to avoid repetition. I've used this functionality often. I like to avoid redundancy in implementing a common use-case.

    @Frank -- Yes, I know the name is awkward, and it needs to be improved. It is basic functionality, but I would think that other programmers have used the same functionality often.

    @Andre -- You would not be storing the default value in the keyed container, you would be binding a new keyed entry in the container to an initial default value. Imagine, for a simple case, that you are using a QMap as an indexing word counter. You are going to be initializing each entry in the map with zero every time a new word is encountered. Now, you could use the defaultValue argument of the value() function to return 0 if the word didn't exist in the index. However, you would still have to set the entry key-value pair explicitly.

  • Here's an example of my most recent use of this functionality from some code that I edited a few days ago:
    if( !_dataMap.contains( dataKey ) )
    _dataMap.insert( dataKey, Datum( sampleName, elemName) );
    Datum& datum = _dataMap[dataKey];

Log in to reply