简体   繁体   中英

Initialise a lambda function to be passed as a predicate to std::find_if in C++

I'm trying to initialise a lambda function and then passing as a predicate to std::find_if but receiving the following compiler error. "expression cannot be used as a function".

So how do you first initialise a lambda as a type auto variable and pass it in as a predicate function to an algorithm like std::find_if?

#include <iostream>
#include <vector>
#include <algorithm>
    
    
int main()
{
    std::vector<std::string> vec ={"this", "is", "a", "test", "to",
                                    "see","if", "this", "works", "to", "this", "if"};
    
    auto elimDups_lambda
        {
            [&vec]()
            {
                std::sort(vec.begin(), vec.end());
                vec.erase(std::unique(vec.begin(), vec.end()), vec.end());
                return vec;
            }
        };
    
    for(auto& iter_vec:elimDups_lambda())
            std::cout<<iter_vec<<std::endl;
    
    
    auto lambda_size
        {
            [&vec](size_t x)
            {
                for(auto& iter_vec:vec)
                {
                    if(iter_vec.size()==x)
                        return true;
                    else if(iter_vec >*vec.end())
                        return false;
                }
            }
        };
    
    
     size_t string_size =0;
     std::cin>>string_size;
    
     std::vector<std::string>::iterator find_word =
     std::find_if(vec.begin(), vec.end(), lambda_size(string_size));
    
     std::cout<<*find_word<<std::endl;
        
     return 0;
}

Thank you.

With the expression

lambda_size(string_size)

you call the lambda function, and then the returned bool result will be used as the predicate for std::find_if .

This will of course not work very well.

You can solve this in two ways:

  1. Capture string_size in the lambda; Or

  2. Make the lambda return another lambda for the size check:

     auto lambda_size = [&vec](size_t size) { return [size](std::string const& word) { return word.length() == size; } }

Also note how I have changed the logic in the lambda for the comparisons. Your comparison could mean that you dereference the end() iterator for the vector, which isn't allowed. And also that there's a path where the lambda doesn't actually return anything.

Both those problems inside the lambda would lead to undefined behavior .

In order to define a variable holding a lambda, you can use syntax similar to this:

auto lambda_var = 
    [&vec]()
    {
        std::sort(vec.begin(), vec.end());
        vec.erase(std::unique(vec.begin(), vec.end()), vec.end());
        return vec;
    };

To use it when calling std::find_if , pass lambda_var (or the name of the variable holding the lambda that you need), as a 3rd parameter to std::find_if

in your code elimDups_lambda and lambda_size are not properly defined to be variables holding lambdas (if this is indeed what you wanted to achieve).

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