Как адаптировать лямбды C к интерфейсу приемника, такому как back_inserter и др.

#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 не подходит. Так ли это?