对std :: hash <string>的未定义引用

hao*_*ang 2 c++ c++11

我正在尝试编写一个简单的工厂函数std::unordered_map.该函数接受一个iterable,它有一个beginend方法,并且value_type是a std::pair.以下是我提出的代码.

#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;
}
Run Code Online (Sandbox Code Playgroud)

但是,我得到一个很长的链接器错误列表,它基本上要求std::hash专门的类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'
Run Code Online (Sandbox Code Playgroud)

我正在使用GCC 4.6.1,有-std=c++0x选项.我非常肯定std::hash<std::string>已定义basic_string.h,包括在内<string>.

知道这是怎么回事吗?

Ker*_* SB 5

你的类型扣除混淆了.从推断的类型中删除限定符非常重要,因此请按以下方式声明模板:

#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());
}
Run Code Online (Sandbox Code Playgroud)

如果没有这个,你最终会const std::string成为关键类型,而没有专业化std::hash.

查看如何编写真实世界的库代码(例如GCC标准库实现),以了解如何明智地处理模板类型.

(顺便说一句,std::equal可能不是无序地图的最佳工具.)