Могу ли я написать шаблонную функцию для вектора и карты одновременно? - PullRequest
0 голосов
/ 06 августа 2020

Есть ли способ написать шаблонную функцию для итераторов контейнера STL, которая работает для std::vector и std::map? Следующая функция работает для std::vector<T>, std::array<T>, std::list<T>

template<class Iterator>
void fun(Iterator f, Iterator l)
{
    for(; f != l; ++f)
    {
        doWork(*f); // or maybe f->doSomething();
    }
}

Проблема в том, что итератор карты указывает на пару ключ и значение. Могу ли я как-то перегрузить функцию, чтобы принять map<whatever,T>?

Ответы [ 2 ]

2 голосов
/ 06 августа 2020

Если вы можете использовать C ++ 17, вы можете использовать if constexpr, чтобы определить, имеете ли вы дело с парой или значением.

#include <map>
#include <vector>
#include <type_traits>

template<class T>
void doWork(T t) {
    t *=2;
}

template <typename T>
struct is_pair : std::false_type { };

template <typename T, typename U>
struct is_pair<std::pair<T, U>> : std::true_type { };

template<class Iterator>
void fun(Iterator f, Iterator l)
{
    for(; f != l; ++f)
    {
        if constexpr(is_pair<std::decay_t<decltype(*f)>>::value) {
            doWork(f->second);
        } else {
            doWork(*f);
        }

    }
}
int main()
{
    std::vector<int> v;
    std::map<int,int> m;

    fun(v.begin(), v.end());
    fun(m.begin(), m.end());
}
2 голосов
/ 06 августа 2020

Я думаю, вы хотите работать со всеми значениями. В таком случае я бы написал функцию getValue , специализировал бы ее для пары и сделал бы форвардом для всех других типов. Затем используйте его в fun .

#include <iostream>
#include <map>
#include <vector>

template <class T, class U> U & getValue(std::pair<T,U> & p) { return p.second; }
template <class T> T && getValue(T && t) { return std::forward<T>(t); }

void doWork(int) {}

template<class Iterator>
void fun(Iterator f, Iterator l)
{
  for(; f != l; ++f)
    {
      doWork(getValue(*f));
    }
}

int main()
{
  std::map<int, int> m;
  std::vector<int> v;
  fun(m.begin(), m.end());
  fun(v.begin(), v.end());
}
...