Вы перепутали алгоритм. То, что вам нужно ::std::accumulate
, a ::std::reduce
- это обобщенная сумма. При его выполнении первый элемент в функторе может быть значением символа из входящей строки, а не накопленное значение.
Обратите внимание на требования алгоритма:
T must meet the requirements of MoveConstructible. and binary_op(init, *first)
, binary_op(*first, init)
, binary_op(init, init)
, and binary_op(*first, *first)
must be convertible to T
.
В этом легко убедиться, напечатав значения, поступающие в функтор:
auto op = [](int accum, char c) -> int {
::std::cout << accum << " \"" << c << "\"\n";
return accum + ((c == ' ') ? 1 : 0);
};
online compiler
112 "r"
101 "t"
112 "e"
0 "p"
116 "y"
32 "l"
116 " "
0 "u"
105 "t"
116 "l"
105 "t"
...
При вызове accumulate
происходит то, что вы предполагаете - для каждого элемента вызывается функтор в котором первым аргументом идет накопитель, а вторым - символ из входящей строки. При вызове reduce
в функтор и первым, и вторым аргументом могут подавать и накопитель и символы. reduce
может складывать элементы последовательности между собой (а может и не складывать).
Также важное отличие заключается в требовании ко входящим итераторам - accumulate
работает с input iterator и поэтому работает всегда последовательно и не поддерживает параллелизм, а reduce
имеет перегрузку с forward iterator и может быть выполнен параллельно.
Пример для суммирования массива:
accumulate
4 9 8 5 2 1 0 6
13 ┘ │ │ │ │ │
21 ┘ │ │ │ │
26 ┘ │ │ │
28 ┘ │ │
29 ┘ │
29 ┘
35
reduce
4 9 8 5 2 1 0 6
13 13 3 6
26 9
35
Для использованиея reduce
функтор необходимо переписать
#include <iostream>
#include <string_view>
#include <numeric>
using t_Accum = ::std::size_t;
class t_CountSpaces final
{
private: auto operator ()(char const ch) const noexcept
{
return (' ' == ch) ? t_Accum{1} : t_Accum{0};
}
public: auto operator ()(t_Accum const accum1, t_Accum const accum2) const noexcept
{
return accum1 + accum2;
}
public: auto operator ()(char const ch, t_Accum const accum) const noexcept
{
return accum + (*this)(ch);
}
public: auto operator ()(t_Accum const accum, char const ch) const noexcept
{
return accum + (*this)(ch);
}
public: auto operator ()(char const ch1, char const ch2) const noexcept
{
return (*this)(ch1) + (*this)(ch2);
}
};
auto CountWords(::std::string_view str)
{
return ::std::reduce(str.begin(), str.end(), t_Accum{0}, t_CountSpaces{});
}
int main()
{
// должно вывести 6
::std::cout << CountWords("pretty little octopus dnskdj kjanfkj snfs jknds") << ::std::endl;
return 0;
}
online compiler
А еще стоит отметить, что ни то, ни другое не могут быть использованы в CountWords
для подсчета количества слов. По сути тут считается не количество слов, а количество пробелов (для этого подошел бы ::std::count
).