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

时间:2011-10-10 04:50:12

标签: c++ c++11

我正在尝试为std::unordered_map编写一个简单的工厂函数。该函数采用可迭代的方法,该方法具有beginend方法,其value_typestd::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;
}

但是,我得到一长串链接器错误,它基本上要求专门用于std::hash的{​​{1}}类。

std::string

我正在使用GCC 4.6.1,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' 选项。我非常确定-std=c++0x中定义的std::hash<std::string>已包含在basic_string.h中。

知道这是怎么发生的吗?

1 个答案:

答案 0 :(得分: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());
}

如果不这样做,您最终会将const std::string作为密钥类型,而std::hash没有专门化。

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

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