Объяснить код?

Я наткнулся на этот код. Из вывода я могу сделать вывод, что в массиве остатков хранится остаток массива чисел при делении на 2. Но синтаксис мне незнаком.

#include <iostream>
#include <functional>
#include <algorithm>

using namespace std;

int main ( )
{

int numbers[ ] = {1, 2, 3};

int remainders[3];

transform ( numbers, numbers + 3, remainders, bind2nd(modulus<int>( ), 2) );

for (int i = 0; i < 3; i++)
{
cout << (remainders[i] == 1 ? "odd" : "even") << "\n";
}
return 0;

}

Что делают transform и bind2nd в этом контексте? Я прочитал документацию, но она мне не была понятна.

-2

Решение

std::bind2nd старая функция для привязки значения ко второму параметру функции Он был заменен std::bind и лямбды.

std::bind2nd возвращает вызываемый объект, который принимает один параметр и вызывает завернутый вызываемый объект с этим параметром в качестве первого параметра и связанным параметром в качестве второго параметра:

int foo(int a, int b)
{
std::cout << a << ' ' << b;
}

int main()
{
auto bound = std::bind2nd(foo, 42);
bound(10); // prints "10 42"}

std::bind2nd (и его партнер std::bind1st) устарели в C ++ 11 и удалены в C ++ 17. Они были заменены в C ++ 11 более гибкими std::bind а также лямбда-выражения:

int foo(int a, int b)
{
std::cout << a << ' ' << b;
}

int main()
{
auto bound = std::bind(foo, std::placeholders::_1, 42);
bound(10); // prints "10 42", just like the std::bind2nd example above

auto lambda = [](int a) { foo(a, 42); };
lambda(10); // prints "10 42", same as the other examples
}

std::transform вызывает вызываемый элемент для каждого элемента диапазона и сохраняет результат вызова в выходном диапазоне.

int doubleIt(int i)
{
return i * 2;
}

int main()
{
int numbers[] = { 1, 2, 3 };
int doubled[3];

std::transform(numbers, numbers + 3, doubled, doubleIt);
// doubled now contains { 2, 4, 6 }
}
5

Другие решения

std::bind2nd взято из C ++ 98/03 (в частности, pre-lambdas).

bin2nd(f, x) предполагает, что f является функцией (или, по крайней мере, чем-то, что может быть вызвано как функция) и x это значение, которое передается этой функции в качестве ее второго параметра. Это создает что-то, что действует как функция. Когда вы вызываете функцию, которую она создает, это эквивалентно вызову f(something, x), так что binds х ко второму параметру его входной функции.

В настоящее время вы, вероятно, написали бы это больше как:

transform(std::begin(numbers), std::end(numbers),
remainders,
[](int x) { return x % 2; });

Что касается того, что делает transform, то это в значительной степени похоже на цикл, так что это примерно эквивалентно:

for (int i=0; i<3; i++)
remainders[i] = numbers[i] % 2;

В целом, я думаю, что оригинальный код наполовину испечен. Мне кажется, это было написано, когда все это было довольно новым (или, по крайней мере, новым для автора). Если бы я собирался сделать эту работу в целом, я бы, вероятно, немного «свернул» операции:

std::transform(std::begin(numbers), std::end(numbers),
std::ostream_iterator<std::string>(std::cout, "\n"),
[](int i) { return std::to_string(i) + (i % 2 == 0 ? " is even" : " is odd"); });

Оригинал, кажется, не имеет никакого смысла для remainders массив, за исключением хранения промежуточного значения перед выводом результата, так что, вероятно, лучше его вообще не создавать / заполнять.

3

По вопросам рекламы [email protected]