Ошибка параметра шаблона скрытого шаблона

Я пытаюсь создать функцию, которая получает ключи от std::map или std::unordered_map. Я мог бы использовать простую перегрузку, но сначала мне хотелось бы узнать, что не так с этим кодом.

template<typename K, typename V, template<typename, typename> class TContainer>  
std::vector<K> getKeys(const TContainer<K, V>& mMap)
{
    std::vector<K> result;
    for(const auto& itr(std::begin(mMap)); itr != std::end(mMap); ++itr) result.push_back(itr->first);
    return result;
}

При вызове его с std::unordered_map, даже при указании всех типов шаблонов вручную, clang ++ 3.4 говорит:

аргумент шаблона шаблона имеет другие параметры шаблона, чем соответствующий параметр шаблона шаблона.


person Vittorio Romeo    schedule 13.08.2013    source источник


Ответы (1)


Проблема в том, что std::map и std::unordered_map на самом деле не являются шаблонами с двумя параметрами. Они есть:

namespace std {
    template <class Key, class T, class Compare = less<Key>,
              class Allocator = allocator<pair<const Key, T>>>
    class map;

    template <class Key, class T, class Hash = hash<Key>,
              class Pred = equal_to<Key>,
              class Allocator = allocator<pair<const Key, T>>>
    class unordered_map;
}

Вот что-то похожее, что действительно работает:

template <typename K, typename... TArgs, template<typename...> class TContainer>
std::vector<K> getKeys(const TContainer<K, TArgs...>& mMap)
{
    std::vector<K> result;
    for (auto&& p : mMap)
        result.push_back(p.first);
    return result;
}

Версия, которую я бы предпочел:

template <typename Container>
auto getKeys2(const Container& mMap) -> std::vector<typename Container::key_type>
{
    std::vector<typename Container::key_type> result;
    for (auto&& p : mMap)
        result.push_back(p.first);
    return result;
}

Демонстрационная программа, использующая обе функции: http://ideone.com/PCkcu6

person aschepler    schedule 13.08.2013
comment
О, теперь я чувствую себя такой глупой. Есть ли способ сопоставить map и unordered_map без создания двух разных перегрузок? Количество параметров шаблона различается. - person Vittorio Romeo; 14.08.2013
comment
Отредактировано с возможным исправлением. Но, наверное, лучше бы как-то использовать decltype(mMap)::key_type. - person aschepler; 14.08.2013
comment
Придумал такое же исправление за несколько минут до того, как вы его разместили, хе-хе. Спасибо за все! - person Vittorio Romeo; 14.08.2013
comment
На мой взгляд, большое улучшение. Я изменил auto на const auto& и реализовал его в своей библиотеке. - person Vittorio Romeo; 14.08.2013