#c #lambda #adapter
#c #лямбда #адаптер
Вопрос:
Я хотел бы знать, возможно ли это без необходимости определять дополнительный класс, можно ли адаптировать лямбду для работы в качестве приемника.
Например, в настоящее время мы можем сделать следующее:
std::vector<int> ilst;
std::copy(ilst.begin(),ilst.end(),std::ostream_iterator<int>(std::cout,"n"));
Что, если возможно что-то вроде следующего? очевидно, что следующее не будет
скомпилировать atm:
std::copy(ilst.begin(),ilst.end(),
[](const intamp; i)
{
std::cout << i << "n";
});
Я смог обойти эту проблему, определив объект function, который реализует операторы разыменования и функции и принимает лямбду в качестве предиката.
Однако мне было интересно, существует ли какой-то C voodoo, который позволит выполнить вышеуказанное без необходимости предоставления дополнительного промежуточного класса?
Комментарии:
1. Помните, что адаптер уже есть: boost.org/doc/libs/1_47_0/libs/iterator/doc /…
2. @avakar: Уже упоминалось, что я ищу решения, позволяющие обойти наличие такого адаптера.
Ответ №1:
Вы не можете сделать это без объекта адаптера.
std::copy
использует итератор вывода, который соответствует требованиям итератора вывода стандартной библиотеки. Лямбда-функция — это объект, который имеет operator()
, который принимает определенные аргументы и возвращает значение. Это два разных вида вещей.
Если у вас есть интерфейс, который принимает Y, но у вас есть X, единственный способ согласовать это — ввести Z, который преобразует X в Y.
И поскольку X и Y являются объектами, следовательно, Z должен быть объектом, который предоставляет интерфейс Y, но внутренне преобразует его в X. Z обычно называют объектом адаптера.
Нет альтернативы «C voodoo», которая изменит это. «Другого решения» не существует. Вы должны использовать какой-то адаптер. Является ли это временным типом класса или функцией, которая возвращает экземпляр класса, это может быть разрешено только с помощью объекта адаптера.
Применительно к этой конкретной ситуации — X — это лямбда-выражение, Y — итератор вывода, а Z — function_output_iterator:
#include <boost/function_output_iterator.hpp>
#include <boost/range/algorithm/copy.hpp>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> ilst;
boost::copy(
ilst,
boost::make_function_output_iterator(
[](int i) { std::cout << i << "n"; }));
}
Комментарии:
1. Я ценю ответ, но, как указано в вопросе, я уже знаю о таких адаптерах и больше искал другие виды решений — предоставление ответа на то, что было конкретно указано как не обязательное или желаемое, очевидно, не в SO, скорее это то, что с радостью сделал бы кто-то, ищущий точки.
2. @JaredKrumsie: Вы спросили: «Однако мне было интересно, существует ли какой-то C voodoo, который позволит выполнить вышеуказанное без необходимости предоставления дополнительного промежуточного класса?» И я ответил: «Используемый вами «C voodoo» называется объектом адаптера, который переводит один интерфейс в другой. Это не только правильное решение, но и единственное решение.» Конечно, вы можете не верить этому ответу. Но это не сделает это менее правдивым
![]()
3. Я согласен, что это решение «a», поскольку я заявил, что текущее решение, которое я использовал, было таким, однако меня интересовали другие решения. Вы представили ответ, который по существу повторил то, что я сказал, и все же каким-то волшебным образом вы получили 3 голоса, похоже, что марионеточные избиратели живы и здоровы и следуют за мистером Николом. ; D
4. @JaredKrumsie: Я не уверен, в чем проблема. Вы просили «другие решения». Других решений нет , что, как я думал, я четко изложил в своем ответе. Но, поскольку вы настаиваете, я сделаю это первой строкой, чтобы было понятно.
Ответ №2:
Будет ли это делать то, что вы ожидаете?
std::for_each(ilst.begin(),ilst.end(),
[](const intamp; i)
{
std::cout << i << "n";
});
Я подозреваю, что этот пример является заменой для чего-то более сложного, где for_each не подходит. Так ли это?