Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template function to receive a generic map as a parameter

There may be many case in which we want to perform some operation on a std::map or a std::unordered_map that is exactly the same, independently from the type of the map. Let us consider the following example:

#include <map>
#include <unordered_map>
#include <iostream>

template< template <typename,typename> class Container >
void printMap(Container<int, long> inputMap, bool additionalParam = false)
{
    for (const pair<int,long> p : inputMap)
        cout<<p.first <<","<< p.second <<std::endl;
}

int main()
{
int a = 1;
long b = 2;
map<int,long> map1;
map1.emplace(a,b);
unordered_map<int,long> map2;
map2.emplace(a,b);
printMap(map1);
printMap(map2);

return EXIT_SUCCESS;
}

If I try to compile the example above, I have this:

error: no matching function for call to ‘printMap(std::map<int, long int>&)’

I read about the use of template of template in this post. What is the right way to do that?

like image 797
Andrea Araldo Avatar asked Aug 09 '17 21:08

Andrea Araldo


2 Answers

Try with

template< template <typename...> class Container, typename ... Ts >
void printMap(Container<int, long, Ts...> inputMap,
              bool additionalParam = false)

The (bigger) problem in your code is that std::map and std::unordered_map are template classes with four (not two) template parameters. The 3rd and the 4th have default value so you can define a std::map object as

 std::map<int, long> map1;

but, with default parameter, you're defining it as

 std::map<int, long, std::less<int>,
          std::allocator<std::pair<const int, long> >> map1;

(ps: or you can make it simple and use auto, as in the Semyon Burov's solution; +1)

like image 183
max66 Avatar answered Sep 20 '22 08:09

max66


Compiler cant deduce template argument if you define it that way. Try to use:

template<typename Map>
void printMap(const Map& map, bool additionalParam = false) {
    for (const auto& p : map)
        cout<<p.first <<","<< p.second <<std::endl;
}

If you need to check, that Map is exactly Map<int, long int>, then add static assertion to a body of function:

static_assert( std::is_same< typename Map::key_type, int >::value &&
                       std::is_same< typename Map::mapped_type, long >::value, "!");
like image 23
Semyon Burov Avatar answered Sep 20 '22 08:09

Semyon Burov