Функция Generi c, которая получает разные контейнеры STL [C ++] - PullRequest
0 голосов
/ 02 августа 2020

У меня вопрос по коду C ++. Моя задача - создать общую c функцию, которая принимает разные контейнеры STL (вектор, список, набор) и считает в них нечетные числа.

Моя первая попытка:

template <typename T>
void countOdd(T x)
{
    int count = 0;
    for (int i = x.begin(); i < x.size(); i++)
        if (x % 2 == 1)
            count++;
    cout << count;
}

Однако у меня много ошибок, и я считаю, что это неправильный путь.

Ответы [ 3 ]

5 голосов
/ 02 августа 2020

У вас ряд проблем. Это l oop:

for (int i = x.begin(); i < x.size(); i++)

неверно. begin() возвращает итератор, а не индекс.

Также это условие:

if (x % 2 == 1)

неверно, поскольку x - это передаваемый диапазон, а не отдельные элементы.

Самый простой способ сделать это:

template<typename T>
void countOdd(T const & range)
{
    int count = 0;
    for (auto const &element : range)
        if (element % 2 != 0)
            count++;
    cout << count;
}

Начиная с C ++ 20, вы можете уменьшить шаблон для шаблона и написать:

void countOdd(auto const & range)
{
    int count = 0;
    for (auto const &element : range)
        if (element % 2 != 0)
            count++;
    cout << count;
}

И, наконец, , вы должны использовать соответствующий алгоритм, чтобы вы могли:

void countOdd(auto const & range)
{
  cout << std::count_if(std::begin(range), std::end(range),
                        [](auto element) { return element % 2 != 0; });
}
1 голос
/ 02 августа 2020

Вам нужно template.

, тогда более распространенный атрибут - это начало / конец вместо начала / размера (и итератор начала возврата, а не int)

, так что вы можете

template <typename Container>
std::size_t countOdd(const Container& cont)
{
    return std::count_if(std::begin(cont), std::end(cont),
                         [](auto e){ return e % 2 != 0; });
}
0 голосов
/ 02 августа 2020

Функция, которую вы должны реализовать, является примером использования std::count_if. Возможная реализация из cppreference :

template<class InputIt, class UnaryPredicate>
typename iterator_traits<InputIt>::difference_type
    count_if(InputIt first, InputIt last, UnaryPredicate p)
{
    typename iterator_traits<InputIt>::difference_type ret = 0;
    for (; first != last; ++first) {
        if (p(*first)) {
            ret++;
        }
    }
    return ret;
}

Стандартные алгоритмы принимают итераторы в качестве параметра, а контейнер предоставляет методы для получения итераторов для первого элемента begin() и одного прошедшего последний элемент end().

Предикат - это вызываемая функция, которая принимает элемент в качестве параметра и возвращает bool, чтобы указать, следует ли подсчитывать элемент или нет.

Мы можем обернуть это в функцию, которая принимает контейнер в качестве параметра:

#include <iostream>
#include <algorithm>
#include <vector>

template <typename Container>
auto count_odds(const Container& c) {
    auto is_odd = [](auto element)->bool { return element % 2;};
    return std::count_if(c.begin(),c.end(),is_odd);
}


int main() {
    std::vector<int> v{1,2,3,4};
    std::cout << count_odds(v);
}
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...