Using Boost adaptors with C++11 lambdas

岁酱吖の 提交于 2019-11-26 14:21:28

问题


I tried to compile this code:

#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>
#include <vector>

int main() {
    std::vector<int> v{
        1,5,4,2,8,5,3,7,9
    };
    std::cout << *boost::min_element(v | boost::adaptors::transformed(
            [](int i) { return -i; })) << std::endl;
    return 0;
}

The compilation failed with the following error message (after a long template instantiation novel):

/usr/local/include/boost/iterator/transform_iterator.hpp:84:26: error: use of deleted function ‘main()::<lambda(int)>::<lambda>()’
../main.cpp:12:5: error: a lambda closure type has a deleted default constructor

I googled the problem, and found this in the Boost Users mailing list archive. It suggested that using #define BOOST_RESULT_OF_USE_DECLTYPE would solve the problem. I put it into the very beginning of my code, but it still doesn't compile. The length of the error message seems to be much shorter, but the error message at the end is the same. I'm currently using Boost 1.50.

What can be the problem here? Is there any way to make this work?


回答1:


http://smellegantcode.wordpress.com/2011/10/31/linq-to-c-or-something-much-better/

But you can use this, that works well.

#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>
#include <vector>
#include <functional>

int main() {
    std::vector<int> v{
        1,5,4,2,8,5,3,7,9
    };
    std::function<int(int)> func = [](int i) { return -i; };
    std::cout << *boost::min_element(v | boost::adaptors::transformed(
    func)) << std::endl;
    return 0;
}

http://liveworkspace.org/code/b78b3f7d05049515ac207e0c12054c70

#define BOOST_RESULT_OF_USE_DECLTYPE works fine in VS2012 for example.




回答2:


You can turn a non-capturing lambda into a function pointer by putting a "+" in front of it.

std::vector<int> v{1,5,4,2,8,5,3,7,9};
std::cout << *boost::min_element(v | 
    boost::adaptors::transformed(+[](int i) 
    {
        return -i; 
    })) << std::endl;



回答3:


This is covered at http://boost.2283326.n4.nabble.com/range-cannot-use-lambda-predicate-in-adaptor-with-certain-algorithms-td3560157.html and https://svn.boost.org/trac/boost/ticket/4189 - the problem is that some algorithms expect to be able to copy-construct (and default-construct, and copy-assign) their predicate, which can't be done with a lambda.

The workaround is to wrap the lambda in a std::function:

*boost::min_element(
    v | boost::adaptors::transformed(std::function<int(int)>(
        [](int i) { return -i; })));

I've asked (at Inferring the call signature of a lambda or arbitrary callable for "make_function") for a way to write a make_function such that one can just write:

*boost::min_element(
    v | boost::adaptors::transformed(make_function(
        [](int i) { return -i; })));



回答4:


With C++17 feature class template argument deduction you can wrap with std::function simplier, like this:

*boost::min_element(
    v | boost::adaptors::transformed(std::function(
        [](int i) { return -i; })));


来源:https://stackoverflow.com/questions/11872558/using-boost-adaptors-with-c11-lambdas

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!