неопределенная ссылка на std :: hash <string> - PullRequest
2 голосов
/ 10 октября 2011

Я пытаюсь написать простую фабричную функцию для std::unordered_map.Функция принимает итеративный метод, который имеет метод begin и end и чей value_type равен 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;
}

Однако я получаю длинный список ошибок компоновщика, и в основном запрашивается класс 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'

Я использую GCC 4.6.1 с опцией -std=c++0x.Я почти уверен, что std::hash<std::string> определен в basic_string.h, который включен в <string>.

Есть идеи, как это происходит?

1 Ответ

5 голосов
/ 10 октября 2011

Вы путаете вычеты по типу.Важно удалить квалификаторы из выведенных типов, поэтому объявите свой шаблон следующим образом:

#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 - этовероятно, не лучший инструмент для неупорядоченных карт.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...