Tuesday, October 23, 2018

c++ - unordered_map constructor error (equal_to templated function)



I thought I could have a pointer to a fully-specialized template function, but the following code isn't compiling (MSVC2012)



#include 
#include
#include
#include

using namespace std;


unsigned long hashing_func(string key)
{
unsigned long hash = 0;
for(int i=0; i {
hash += (71*hash + key[i]) % 5;
}
return hash;
}


bool key_equal_fn2(string t1, string t2)
{
return t1 == t2;
}


template bool key_equal_fn(T t1, T t2)
{
return t1 == t2;

}

template <> bool key_equal_fn(string t1, string t2)
{
return !(t1.compare(t2));
}

int main ()
{
unordered_map::size_type n = 5;

unordered_map mymap(n, (const std::hash &)hashing_func, (const std::equal_to &)(key_equal_fn)) ;

mymap["paul"] = "jenna";
mymap["frank"] = "ashley";


return 0;
}



The constructor line is returning the following error:




error C2440: 'type cast' : cannot convert from 'bool (__cdecl *)(T,T)'
to 'const std::equal_to<_Ty> &'



Answer



Both hashing_func and key_equal_fn should be functor objects (and not functions). In addition, their types must be provided to the unordered_map template, that is, the map should have this type:



unordered_map



where hashing_func and key_equal_fn are functor classes:



struct hashing_func {
unsigned long operator()(const string& key) const {
unsigned long hash = 0;
for(size_t i=0; i hash += (71*hash + key[i]) % 5;
return hash;

}
};

struct key_equal_fn {
bool operator()(const string& t1, const string& t2) const {
return !(t1.compare(t2));
}
};



Then, mymap is defined in this way:



typedef unordered_map MapType;
MapType::size_type n = 5;
MapType mymap(n, hashing_func(), key_equal_fn());


Alternatively, hashing_func and/or key_equal_fn can be functions but you have to wrapp them into std::function objects. That is,



unsigned long hashing_func(const string& key) {

unsigned long hash = 0;
for(size_t i=0; i hash += (71*hash + key[i]) % 5;
return hash;
}

bool key_equal_fn(const string& t1, const string& t2){
return !(t1.compare(t2));
}



and define mymap in this way



typedef unordered_map    std::function,
std::function> MapType;

MapType::size_type n = 5;
MapType mymap(n, hashing_func, key_equal_fn);



If you wish, you can use lambdas and refrain from writing the two funcions or functor classes:



typedef unordered_map    std::function,
std::function> MapType;

MapType mymap(n,
[](const string& key) -> unsigned long {
unsigned long hash = 0;

for(size_t i=0; i hash += (71*hash + key[i]) % 5;
return hash;
},
[](const string& t1, const string& t2) {
return !(t1.compare(t2));
});


Finally, my favorite is an all-lambdas solution




auto hashing_func = [](const string& key) -> unsigned long {
unsigned long hash = 0;
for(size_t i=0; i hash += (71*hash + key[i]) % 5;
return hash;
};

auto key_equal_fn = [](const string& t1, const string& t2) {
return !(t1.compare(t2));

};

typedef unordered_map decltype(hashing_func), decltype(key_equal_fn)> MapType;

MapType::size_type n = 5;
MapType mymap(n, hashing_func, key_equal_fn);

No comments:

Post a Comment

plot explanation - Why did Peaches&#39; mom hang on the tree? - Movies &amp; TV

In the middle of the movie Ice Age: Continental Drift Peaches' mom asked Peaches to go to sleep. Then, she hung on the tree. This parti...