Как std::transform и std::plus работают вместе?

Я читал справочник С++ и наткнулся на функцию std::plus с примером. Что довольно прямолинейно, он просто добавляет левые и правые. Код был:

#include <functional>
#include <iostream>

int main()
{
   std::string a = "Hello ";
   const char* b = "world";
   std::cout << std::plus<>{}(a, b) << '\n';
}

вывод: Привет мир

я изменил его на

#include <functional>
#include <iostream>

int main()
{
   int a = 5;
   int b = 1;
   std::cout << std::plus<int>{}(a, b) << '\n';
}

выход : 6

Теперь я сделал

foo vector = 10 20 30 40 50
bar vector = 11 21 31 41 51

Я позвонил:

std::transform (foo.begin(), foo.end(), bar.begin(), foo.begin(), std::plus<int>());

и он дал 21 41 61 81 101, что, как я понимаю, суммирует как foo, так и bar. Но как это передавалось в функцию std::plus?


person mlhazan    schedule 23.02.2016    source источник
comment
Разве это не ответ на ваш вопрос? Я думаю, вы уже посмотрели на это, иначе вы не поняли бы, как вызвать std::transform. en.cppreference.com/w/cpp/algorithm/transform   -  person 5gon12eder    schedule 23.02.2016


Ответы (2)


std::plus<> — это functor, что является просто причудливой фразой для класса, реализующего operator(). Вот пример:

struct plus {
    template <typename A, typename B>
    auto operator()(const A& a, const B& b) const { return a + b; }
};

Имеющийся у вас std::transform примерно эквивалентен следующему:

template<typename InputIt1, typename InputIt2, 
         typename OutputIt, typename BinaryOperation>
OutputIt transform(InputIt1 first1, InputIt1 last1, InputIt2 first2, 
                   OutputIt d_first, BinaryOperation binary_op)
{
    while (first1 != last1) {
        *d_first++ = binary_op(*first1++, *first2++);
    }
    return d_first;
}

Здесь binary_op — это имя, данное std::plus<>. Поскольку std::plus<> является функтором, C++ интерпретирует «вызов» его как вызов функции operator(), что дает нам желаемое поведение.

person Brian Rodriguez    schedule 23.02.2016
comment
Это был пример для демонстрационных целей, а не для включения в стандарт. - person Kurt Stutsman; 23.02.2016
comment
Что вы подразумеваете под обычно, это приведет к сбою во время компиляции - person M.M; 23.02.2016
comment
@M.M Если бы это не был функтор/если бы он не реализовал operator(). - person Brian Rodriguez; 23.02.2016

std::plus один из набора функторов, предоставляемых STL. Если вы знакомы с функциональным программированием, они удобны для композиции функций. std::plus — это бинарный оператор, поэтому он принимает два аргумента. std::Transform отправит ему элементы из двух векторов. Вы также можете использовать std::bind, чтобы превратить бинарные операторы в операторы с одним аргументом, фактически привязывая константу ко второму аргументу.

Лично я думаю, что std::plus и ему подобные были более полезны до появления c++11 лямбда функции. Lambda позволяет вам определить набор операций для выполнения с вашими данными без необходимости иметь дело с привязками или std::plus и тому подобным.

person Atifm    schedule 23.02.2016