Question

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?

Was it helpful?

Solution

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.

OTHER TIPS

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;

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; })));

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; })));
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top