Home > database >  Function to provide a default value when working with std::map
Function to provide a default value when working with std::map

Time:01-01

I am trying to write a function, which will give me a default value when the key is not inside a std::map. In all cases will my default value be numerical_limit::infinity(). Hovewer this simple example is not working.

#include <iostream>
#include <map>
#include <limits>

template<typename KeyType, typename ValueType>
ValueType mapDefaultInf(const std::map<KeyType, ValueType> & map, const KeyType & key)
{
    if(!map.contains(key))
    {
        return std::numeric_limits<ValueType>::infinity();
    }
    else
    {
        return map[key];
    }
}

int main()
{
    std::map<std::string, int> map;
    auto el = mapDefaultInf(map, "alexey");
    std::cout << el << std::endl;

    return 0;
}

Error is:

main.cpp:29:42: error: no matching function for call to ‘mapDefaultInf(std::map, int>&, const char [7])’

Can someone help me understand the error.

Thanks in advance.

CodePudding user response:

You have constrained your template too much, as it is written it requires the keys in the map to be the of the same type as key parameter.

That fails because your map stores std::string but you pass a string literal which technically has a type of const char[7].

Just make the header:

template<typename KeyType, typename ValueType,typename T>
ValueType mapDefaultInf(const std::map<KeyType, ValueType> & map, const T& key)

It will allow implicit conversions to take place at map.contains(key) call and will just fail with more complicated error message if you pass it an incompatible type. It's not like the current error is a pinnacle of readability anyway.

CodePudding user response:

First of all you use operator[] on the map object inside the function. That will never be allowed because it is a non-const function and you have passed the map by const reference. Instead you should rewrite the function implementation to use iterators:

template<typename KeyType, typename ValueType>
ValueType mapDefaultInf(const std::map<KeyType, ValueType> & map, const KeyType & key)
{
    const auto it = map.find(key);
    return it != map.end() ?  it->second : std::numeric_limits<ValueType>::infinity();
}

Second of all you have an ambiguity in the key type. You need to pass in a std::string. Like this:

auto el = mapDefaultInf(map, std::string("alexey"));
  • Related