C ++: возможно ли сделать параметр функции нескольких типов? - PullRequest
0 голосов
/ 05 мая 2019

Можно ли сделать функцию fun, которая принимает 1 параметр: массив или вектор?Например, это будет работать, если я сделаю это:

Я определю функцию fun(parameter).parameter может быть типа std::vector<int> или int*.Я хочу, чтобы он суммировал все элементы в векторе / массиве.

Это вроде работает как параметры функции python -> это может быть любой тип, но я хочу, чтобы это был вектор или тип массива.

Возможно ли это?

Ответы [ 3 ]

2 голосов
/ 05 мая 2019

Я определяю функцию fun(parameter).Параметр может быть типа std::vector<int> или int*.Я хочу, чтобы он суммировал все элементы в векторе / массиве.

Как вы узнали бы количество элементов только с указателем на int?Обычный способ - передать пару итераторов.

Можете ли вы показать мне пример кода, я никогда не работал с парами?

Вы передаете итератор первомуelement и итератор за последним элементом диапазона, который вы хотите перебрать.В терминологии интервалов это наполовину открыто [first, last):

#include <array>
#include <vector>
#include <list>
#include <iostream>

template<typename ForwardIterator>
long sum(ForwardIterator first, ForwardIterator last)
{
    long sum{};
    while (first != last)
        sum += *first++;
    return sum;
}

int main()
{
    int foo[]{ 1, 2, 3 };
    std::cout << sum(std::begin(foo), std::end(foo)) << '\n';

    std::array<int, 3> bar{ 1, 2, 3 };
    std::cout << sum(bar.begin(), bar.end()) << '\n';

    std::vector<int> qux{ 1, 2, 3 };
    std::cout << sum(qux.begin(), qux.end()) << '\n';

    std::list<int> hugo{ 1, 2, 3 };
    std::cout << sum(hugo.begin(), hugo.end()) << '\n';
}

Черт, вы могли бы также иметь эту функцию только с одним параметром:

#include <array>
#include <vector>
#include <list>
#include <iostream>

template<typename ForwardIterator>
long sum(ForwardIterator first, ForwardIterator last)
{
    long sum{};
    while (first != last)
        sum += *first++;
    return sum;
}

template<typename T>
long sum(T const &container)
{
    return sum(std::begin(container), std::end(container));
}

int main()
{
    int foo[]{ 1, 2, 3 };
    // please note that the array is passed by reference (no pointer):
    std::cout << sum(foo) << '\n';

    // sum(&foo[0]);  // wouldn't work because there is
    // no overload of std::begin() or std::end() for raw pointers

    std::array<int, 3> bar{ 1, 2, 3 };
    std::cout << sum(bar) << '\n';

    std::vector<int> qux{ 1, 2, 3 };
    std::cout << sum(qux) << '\n';

    std::list<int> hugo{ 1, 2, 3 };
    std::cout << sum(hugo) << '\n';
}

Конечно, не изобретайте зановоwheel: std :: аккумулировать

Требования к типу для прямого итератора состоят в том, что он поддерживает операции iterator++ и *iterator++.Простой указатель также может рассматриваться как прямой итератор, поскольку эти операции допустимы с указателями. LegacyForwardIterator .На самом деле, указатель еще более мощный и может использоваться в качестве итератора произвольного доступа. LegacyRandomAccessIterator

Но для решения вашего первоначального вопроса: помимо перегрузки функции для различных параметров или записи шаблона функции, существует также std::variant<> начиная с C ++ 17.

0 голосов
/ 06 мая 2019

Нет необходимости заново изобретать колесо: стандартная библиотека C ++ имеет функцию именно для этой цели: std::accumulate(). Он принимает два аргумента итератора и возвращает сумму элементов (вы также можете указать третий аргумент, который определяет вашу собственную версию оператора сложения, допускающую любой тип операции накопления):

#include <array>
#include <vector>
#include <list>
#include <numeric>
#include <iostream>

int main()
{
    int foo[]{ 1, 2, 3 };
    std::cout << std::accumulate(std::begin(foo), std::end(foo)) << '\n';

    std::array<int, 3> bar{ 1, 2, 3 };
    std::cout << std::accumulate(bar.begin(), bar.end()) << '\n';

    std::vector<int> qux{ 1, 2, 3 };
    std::cout << std::accumulate(qux.begin(), qux.end()) << '\n';

    std::list<int> hugo{ 1, 2, 3 };
    std::cout << std::accumulate(hugo.begin(), hugo.end()) << '\n';
}
0 голосов

Вы должны переписать функцию, используя то же имя, но другие параметры. Это называется перегрузкой функции, проверьте ее.

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