I'm trying to write a simple factory function for st开发者_开发百科d::unordered_map
. The function takes in an iterable which has a begin
and end
method and whose value_type
is a std::pair
. The following is the code that I come up with.
#include <string>
#include <unordered_map>
#include <cassert>
#include <algorithm>
template <class Iterable>
std::unordered_map<typename Iterable::value_type::first_type,
typename Iterable::value_type::second_type>
make_unordered_map(Iterable const &iter)
{
return std::unordered_map<typename Iterable::value_type::first_type,
typename Iterable::value_type::second_type>(
iter.begin(), iter.end());
}
int main()
{
std::unordered_map<std::string, int> map =
{{"a", 0}, {"b", 1}, {"c", 2}};
auto result = make_unordered_map(map);
assert(std::equal(result.begin(), result.end(), map.begin()));
return 0;
}
However, I get a long list of linker error, and it basically asks for the std::hash
class specialized for std::string
.
undefined reference to `std::hash<std::basic_string<char, std::char_traits<char>,
std::allocator<char> > const>::operator()(std::basic_string<char,
std::char_traits<char>, std::allocator<char> >) const'
I'm using GCC 4.6.1, with the -std=c++0x
option. I'm pretty sure std::hash<std::string>
is defined in basic_string.h
, which is included in <string>
.
Any idea how this happens?
You're getting your type deduction mixed up. It's important to remove qualifiers from the deduced types, so declare your template like this:
#include <functional>
template <class Iterable>
std::unordered_map<typename std::decay<typename Iterable::value_type::first_type>::type,
typename Iterable::value_type::second_type>
make_unordered_map(Iterable const &iter)
{
return std::unordered_map<
typename std::decay<typename Iterable::value_type::first_type>::type,
typename Iterable::value_type::second_type>(iter.begin(), iter.end());
}
Without this, you end up with const std::string
as the key type, for which there is no specialization of std::hash
.
Check out how real-world library code is written (e.g. the GCC standard library implementation) to see how to handle template types judiciously.
(By the way, std::equal
is probably not the best tool for unordered maps.)
精彩评论