Определение функции, чтобы она могла принимать либо список, либо вектор - PullRequest
2 голосов
/ 09 марта 2019

У меня есть функция, которая должна получать std::list или std::vector из MyClass * объектов и выполнять кучу обработки в зависимости от того, что внутри. Я не хочу дублировать тело функции.

Мне нужно только использовать эти объекты, чтобы перебрать их и выполнить некоторые проверки только для чтения.

Я думал о непосредственной передаче итераторов .begin() и .end(), но это совсем не похоже.

Есть ли лучший способ обойти это, в настоящее время у меня есть следующее решение (которое создает другой список из передаваемого вектора, что тоже вряд ли идеально).

void process(std::list<MyClass*> input)
{
    //A lot of processing
    BOOST_FOREACH(MyClass* itMyClass, input)
    {
        //some checks, creating new list based on the checks      
    }
    //A lot of processing
}
void process(std::vector<MyClass*> input)
{
    process(std::list<MyClass*>(input.begin(), input.end()));
}

EDIT:

Кажется, что многие люди предлагают перейти на begin() и end(), в конце концов, я заставил это работать так, как показано в примере ниже. Спасибо за вашу помощь.

//This one is private
template <typename Iterator>
void process(Iterator begin, Iterator end)
{
    //A lot of processing
    for (; begin != end; ++begin) 
    {
        //some checks, creating new list based on the checks
    }
    //A lot of processing
}
void process(std::list<MyClass*> input)
{
    process(input.begin(), input.end());
}
void process(std::vector<MyClass*> input)
{
    process(input.begin(), input.end());
}

Ответы [ 2 ]

4 голосов
/ 09 марта 2019

Для этого вы можете использовать шаблон функции :

template<class ListOrVector>
void process(ListOrVector const& input) {
    //your code
}

//You can also use a template template parameter
template<template<class My, class Alloc = std::allocator<My>> class ListOrVector>
void process(ListOrVector<MyClass*, Alloc> const& input) { ... }

Обратите внимание, что я беру ListOrVector по константной ссылке (const &).Это предотвратит копирование.

РЕДАКТИРОВАТЬ

Я исправил второй пример.class перед ListOrVector отсутствовал, а распределитель был std::allocator<My по умолчанию.

0 голосов
/ 11 марта 2019

Как и обычные функции, шаблоны функций также могут быть перегружены , так что вы можете получить лучшее из обоих миров: алгоритм на основе итератора для больше гибкости и контейнеров для простоты использования.

Таким образом, вы можете использовать перегрузку на основе итератора для обработки поддиапазона контейнера и перегрузку на основе контейнера для обработки всех элементов контейнера.


process(first, last)

Я бы предложил сначала определить шаблон функции process(), который принимает пару итераторов для последовательности элементов, которые вы хотите обработать:

template<typename Iterator>
void process(Iterator begin, Iterator end) {
   for (auto it = begin; it != end; ++it) {
      // ...
   }
}

Это алгоритм на основе итератора (т. Е. Он принимает пару итераторов) и соответствует тому же подходу, которому следуют алгоритмы STL.


process(container)

Затем я бы определил другой шаблон функции process(), который перегружает первого. Эта перегрузка принимает контейнер и вызывает основанную на итераторах версию process() для элементов переданного контейнера:

template<typename Container>
void process(Container const& c) {
   process(std::begin(c), std::end(c));
}

Это алгоритм на основе контейнера , так как он принимает контейнер.


Таким образом, вы можете использовать алгоритм на основе контейнера вместо алгоритма на основе итератора:

std::vector<int> vec{1, 2, 3};
std::list<int> lst{1, 2, 3};
std::array<int, 3> arr{1, 2, 3};
int carr[] = {1, 2, 3};

process(vec);
process(lst);
process(arr);
process(carr);

Этот алгоритм отделен от контейнеров для обработки (например, он работает даже с массивами в стиле C, как вы можете видеть), но вы вызываете его непосредственно в контейнере вместо прохождения итераторов.

Вы всегда можете вызвать перегрузку process(), которая принимает пару итераторов вместо контейнера, если вы не хотите обрабатывать все элементы контейнера, а просто поддиапазон элементов в нем.

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