简体   繁体   中英

How to adapt C++ lambdas to a sink interface such as back_inserter et al

I would like to know if its possible without having to define an extra class, if a lambda can be adapted to act as a sink.

For example we currently can do the following:

std::vector<int> ilst;

std::copy(ilst.begin(),ilst.end(),std::ostream_iterator<int>(std::cout,"\n"));

What if something like the following could be possible? obviously the following wont compile atm:

std::copy(ilst.begin(),ilst.end(),
          [](const int& i)
          {
             std::cout << i << "\n"; 
          });

I've been able to get around this problem, by defining a function object that implements dereference and function operators and takes a lambda as a predicate.

However I was wondering if there is some kind of C++ voodoo that will allow for the above without the need for an extra intermediary class to be provided?

You cannot do this without an adapter object.

std::copy takes an output iterator which conforms to the standard library output iterator requirements. A lambda function is an object that has an operator() that takes certain arguments and returns a value. These are two different kinds of things.

If you have an interface that takes Y, but you have a X, the only way to reconcile this is to introduce a Z that converts X into Y.

And since X and Y are objects, Z must therefore be an object that provides the Y interface, but internally converts it into an X. Z is commonly called an adapter object.

There is no alternative "C++ voodoo" that's going to change this. There is no "other solution". You must use some kind of adapter. Whether it's a temporary of a class type or a function that returns an instance of a class, this can only be resolved with an adapter object.


Applied to this particular situation - X is a lambda, Y is an output iterator, and Z is a 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"; }));
}

Would this do what you expect?

std::for_each(ilst.begin(),ilst.end(),
          [](const int& i)
          {
             std::cout << i << "\n"; 
          });

I suspect that this example is a stand-in for something more complicated, where for_each is unsuitable. Is this so?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM