Функция для работы с контейнерами

Пытался сделать функцию accumulate по функционалу такую же как в std. Скажите как исправить, пожалуйста.

template <typename T, typename T1>
T1 accumulate(T begin, T end, T1 startvalue, function<T1(T1,T1)> a=
    [](T1 a,T1 b){return a+b;})
{

    for (auto i = begin; i != end; i++)
    {
        startvalue = a(startvalue, *i);
    }
    return startvalue;
}
int main()
{
    vector<int> v{ 2,3,1,234,685,246,76,5658,5657 };

    auto a = accumulate(v.begin(), v.end(), 1, [](int a, int b) {return a * b; });
    cout<<a;
    return 0;
}

Ответы (1 шт):

Автор решения: Eoan Ermine

Не стоит типизировать аргумент a конкретным типом. Типизируйте его таким же образом параметром шаблона, как и все остальные аргументы.

У вас получится:

#include <functional>

// Если пользователь указал собственный бинарный оператор, используем его
template <typename T, typename T1, typename BinaryOperation>
T1 accumulate(T begin, T end, T1 startvalue, BinaryOperation a) 
{

    for (auto i = begin; i != end; i++)
    {
        startvalue = a(startvalue, *i);
    }
    return startvalue;
}

// Если же нет - используем оператор сложения
template <typename T, typename T1>
T1 accumulate(T begin, T end, T1 startvalue)
{
    return accumulate(begin, end, startvalue, std::plus<>{});
}

Также у вас в функции main происходит переполнение значения типа int, из-за чего выводимое значение оказывается неверным. Чтобы избежать этого, следует использовать вместо типа int тип, способный вместить результат выполнения функции:

int main() {
    // ...
    auto a = accumulate(v.begin(), v.end(), 1ll, [](long long a, long long b) {return a * b; });
    // ...
}
→ Ссылка